1354 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1354 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| /* ========================================================================
 | |
|  * Copyright 2018 - Volian Enterprises, Inc. All rights reserved.          
 | |
|  * Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
 | |
|  * ------------------------------------------------------------------------
 | |
|  * This program is to automate the Comparison of PDF output using the debug
 | |
|  * files created during automated testing.  The SQL script is used to create
 | |
|  * the debug files; DebugPagination.txt and DebugMeta.txt.  This comparison 
 | |
|  * code then compares these files run with two versions of the PROMS code
 | |
|  * and finds pages that have been impacted by the changes to the PROMS code.
 | |
|  * 
 | |
|  * By Identifying Procedures and Pages that have been changed the amount of
 | |
|  * time required to perform comparisons is greatly reduced.
 | |
|  * 
 | |
|  * The Pagination Comparison simply looks for things that have impacted page
 | |
|  * breaks.  This is a quick summary of the page breaks for all of the 
 | |
|  * procedures in a folder.  Thus, the folders are listed which contain 
 | |
|  * differences.  When a folder is selected, the pagination information is 
 | |
|  * compared for all of the procedures in each folder.  If no changes exits,
 | |
|  * then the folder is not contained in the list. after selecting a folder,
 | |
|  * a comparison is shown of the pagination lines that are different.  
 | |
|  * Pressing the UC button allows you to see ultracompare with the two
 | |
|  * pagination files.  If you select a line that is different, two pdf
 | |
|  * windows are opened to the relative pages.
 | |
|  * 
 | |
|  * The Meta Comparison looks at more detail including text and formatting
 | |
|  * differences.  This information is organized by procedure and page.  It 
 | |
|  * uses the procedure/page/line classes.  The structure of this file is 
 | |
|  * described in 
 | |
|  * V:\Proms Versions\Automated Testing\Baseline Metafile Key.docx
 | |
|  * By Clicking on a folder a list of impacted procedures is provided.  
 | |
|  * By clicking on a Procedure a list of pages and lines are provided.
 | |
|  * By clicking on a line the PDF is displayed.
 | |
|  * 
 | |
|  * The Search feature performs a text search on the Meta File.  Looking 
 | |
|  * for RCP will tell you where RCP can be found in the PDFs.  This may be 
 | |
|  * of use if you want to see where certain text is contained within all of 
 | |
|  * the PDFs.  Looking for [[ will find all of the special characters which
 | |
|  * have not yet been handled in the PROMS meta code.  See FixText in 
 | |
|  * DisplayText.cs in the PROMS code.
 | |
|  * ======================================================================*/
 | |
| 
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.ComponentModel;
 | |
| using System.Data;
 | |
| using System.Drawing;
 | |
| using System.Linq;
 | |
| using System.Text;
 | |
| using System.Threading.Tasks;
 | |
| using System.Windows.Forms;
 | |
| using System.Collections.Specialized;
 | |
| using System.IO;
 | |
| using System.Text.RegularExpressions;
 | |
| using System.Xml.Serialization;
 | |
| using System.Xml.Schema;
 | |
| using System.Xml;
 | |
| using System.Runtime.InteropServices;
 | |
| 
 | |
| namespace Baseline
 | |
| {
 | |
| 	enum LastWas
 | |
| 	{
 | |
| 		Pagination,
 | |
| 		Baseline,
 | |
| 		Search
 | |
| 	};
 | |
| 	public enum Relation
 | |
| 	{
 | |
| 		Contains,
 | |
| 		StartsWith,
 | |
| 		EndsWith,
 | |
| 		Regex
 | |
| 	}
 | |
| 	public partial class frmBaseline : Form
 | |
| 	{
 | |
| 		private IgnoreLines _MyIgnore = new IgnoreLines();
 | |
| 		public IgnoreLines MyIgnore
 | |
| 		{
 | |
| 			get { return _MyIgnore; }
 | |
| 			set { _MyIgnore = value; }
 | |
| 		}
 | |
| 		private LastWas myLast = LastWas.Search;
 | |
| 		private Settings MySettings;
 | |
| 		public string MyStatus
 | |
| 		{
 | |
| 			get { return tsslStatus.Text; }
 | |
| 			set
 | |
| 			{
 | |
| 				tsslStatus.Text = value;
 | |
| 				Application.DoEvents();
 | |
| 			}
 | |
| 		}
 | |
| 		public frmBaseline()
 | |
| 		{
 | |
| 			InitializeComponent();
 | |
| 			LoadSettings();
 | |
| 			SetupEventHandlers();
 | |
| 			MyStatus = "Ready";
 | |
| 		}
 | |
| 		#region Settings
 | |
| 		/// <summary>
 | |
| 		/// Setup event handlers for changes to Settings
 | |
| 		/// </summary>
 | |
| 		private void SetupEventHandlers()
 | |
| 		{
 | |
| 			this.Resize += frmBaseline_Resize;
 | |
| 			this.Move += frmBaseline_Move;
 | |
| 			this.splitContainer1.SplitterMoved += splitContainer1_SplitterMoved;
 | |
| 			this.splitContainer2.SplitterMoved += splitContainer2_SplitterMoved;
 | |
| 			this.splitContainer3.SplitterMoved += splitContainer3_SplitterMoved;
 | |
| 			cbFile1.TextChanged += cbFile1_TextChanged;
 | |
| 			cbFile2.TextChanged += cbFile2_TextChanged;
 | |
| 		}
 | |
| 		// Remember the location of splitters
 | |
| 		void splitContainer3_SplitterMoved(object sender, SplitterEventArgs e)
 | |
| 		{
 | |
| 			Properties.Settings.Default.Split3 = splitContainer3.SplitterDistance;
 | |
| 			Properties.Settings.Default.Save();
 | |
| 		}
 | |
| 		void splitContainer2_SplitterMoved(object sender, SplitterEventArgs e)
 | |
| 		{
 | |
| 			Properties.Settings.Default.Split2 = splitContainer2.SplitterDistance;
 | |
| 			Properties.Settings.Default.Save();
 | |
| 		}
 | |
| 		void splitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
 | |
| 		{
 | |
| 			Properties.Settings.Default.Split1 = splitContainer1.SplitterDistance;
 | |
| 			Properties.Settings.Default.Save();
 | |
| 		}
 | |
| 		// Remember Form Location
 | |
| 		void frmBaseline_Move(object sender, EventArgs e)
 | |
| 		{
 | |
| 			Properties.Settings.Default.Location = this.Location;
 | |
| 			Properties.Settings.Default.Save();
 | |
| 		}
 | |
| 		// Remember Form Size
 | |
| 		void frmBaseline_Resize(object sender, EventArgs e)
 | |
| 		{
 | |
| 			if (this.WindowState == FormWindowState.Normal)
 | |
| 			{
 | |
| 				Properties.Settings.Default.Size = this.Size;
 | |
| 			}
 | |
| 			Properties.Settings.Default.WidnowState = this.WindowState;
 | |
| 			Properties.Settings.Default.Save();
 | |
| 		}
 | |
| 		// Load Settings
 | |
| 		private void LoadSettings()
 | |
| 		{
 | |
| 			this.Location = Properties.Settings.Default.Location;
 | |
| 			this.Size = Properties.Settings.Default.Size;
 | |
| 			this.WindowState = Properties.Settings.Default.WidnowState;
 | |
| 			if(Properties.Settings.Default.Ignore != null && Properties.Settings.Default.Ignore != "")
 | |
| 				MyIgnore = IgnoreLines.Get(Properties.Settings.Default.Ignore);
 | |
| 			MySettings= new Settings();
 | |
| 			MySettings.IgnoreLines = new BindingList<string>();
 | |
| 			splitContainer1.SplitterDistance = Properties.Settings.Default.Split1;
 | |
| 			splitContainer2.SplitterDistance = Properties.Settings.Default.Split2;
 | |
| 			splitContainer3.SplitterDistance = Properties.Settings.Default.Split3;
 | |
| 			if (Properties.Settings.Default.MRU1 != null && Properties.Settings.Default.MRU1.Count > 0)
 | |
| 			{
 | |
| 				cbFile1.Items.Clear();
 | |
| 				foreach (string str in Properties.Settings.Default.MRU1)
 | |
| 					cbFile1.Items.Add(str);
 | |
| 				cbFile1.SelectedIndex = 0;
 | |
| 			}
 | |
| 			if (Properties.Settings.Default.MRU2 != null && Properties.Settings.Default.MRU2.Count > 0)
 | |
| 			{
 | |
| 				cbFile2.Items.Clear();
 | |
| 				foreach (string str in Properties.Settings.Default.MRU2)
 | |
| 					cbFile2.Items.Add(str);
 | |
| 				cbFile2.SelectedIndex = 0;
 | |
| 			}
 | |
| 		}
 | |
| 		#endregion
 | |
| 		/// <summary>
 | |
| 		/// Use FolderBrowserDialog to find folder
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void btnBrowse1_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			fbd.SelectedPath = cbFile1.Text;
 | |
| 			if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
 | |
| 				cbFile1.Text = fbd.SelectedPath;
 | |
| 		}
 | |
| 		private void btnBrowse2_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			fbd.SelectedPath = cbFile2.Text;
 | |
| 			if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
 | |
| 				cbFile2.Text = fbd.SelectedPath;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Open frmSettings to edit ignore list
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void btnSettings_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			string saveOriginal = MyIgnore.ToString();
 | |
| 			frmSettings mySettings = new frmSettings(MyIgnore);
 | |
| 			if (mySettings.ShowDialog() == System.Windows.Forms.DialogResult.OK)
 | |
| 			{
 | |
| 				Properties.Settings.Default.Ignore = MyIgnore.ToString();
 | |
| 				Properties.Settings.Default.Save();
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				MyIgnore = IgnoreLines.Get(saveOriginal);
 | |
| 			}
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Process DebugPagination.txt in all sub-folders 
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void btnPagination_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			myLast = LastWas.Pagination;
 | |
| 			// Initialize lbDifferent DocVersion comparison list
 | |
| 			lbDifferent.DataSource = null;
 | |
| 			lbDifferent.Items.Clear();
 | |
| 			// Initialize line differences for DebugPagination
 | |
| 			lbResults1.Items.Clear();
 | |
| 			lbResults2.Items.Clear();
 | |
| 			MyStatus = "Searching...";
 | |
| 			// Perform DebugPagination Comparison
 | |
| 			FindFiles fnd = new FindFiles(cbFile1.Text, cbFile2.Text, "DebugPagination.txt",MyIgnore);
 | |
| 			lbDifferent.DataSource = fnd;
 | |
| 			lbDifferent.DisplayMember = "File1";
 | |
| 			MyStatus = string.Format("{0} Differences Found", fnd.Count);
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Fill Appropriate List Boxes when an entry is selected in lbDifferent
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void lbDifferent_SelectedIndexChanged(object sender, EventArgs e)
 | |
| 		{
 | |
| 			//Initialize ListBoxes
 | |
| 			lbProcedures.Items.Clear();
 | |
| 			lbResults1.Items.Clear();
 | |
| 			lbResults2.Items.Clear();
 | |
| 			FindFile ff = lbDifferent.SelectedItem as FindFile;
 | |
| 			if (ff != null)
 | |
| 			{
 | |
| 				// Fill Procedure or Result ListBoxes
 | |
| 				switch (myLast)
 | |
| 				{
 | |
| 					case LastWas.Pagination:
 | |
| 						CompareContent(ff.File1, ff.File2);// Compare DebugPagination
 | |
| 						break;
 | |
| 					case LastWas.Baseline:
 | |
| 						CompareContent3(ff.File1, ff.File2);// Compare DebugMeta
 | |
| 						break;
 | |
| 					case LastWas.Search:
 | |
| 						ShowSearchResults(ff.File1, ff.File2);// Perform search on DebugMeta
 | |
| 						break;
 | |
| 					default:
 | |
| 						CompareContent(ff.File1, ff.File2);//Default DebugPagination
 | |
| 						break;
 | |
| 				}
 | |
| 				//CompareOneFile(ff.File1, ff.File2);
 | |
| 			}
 | |
| 		}
 | |
| 		Procedures MyProcs1;
 | |
| 		Procedures MyProcs2;
 | |
| 		/// <summary>
 | |
| 		/// Use LINQ to find  a search string in the DebugMeta Files
 | |
| 		/// </summary>
 | |
| 		/// <param name="file1"></param>
 | |
| 		/// <param name="file2"></param>
 | |
| 		private void ShowSearchResults(string file1, string file2)
 | |
| 		{
 | |
| 			IEnumerable<string> lines1 = File.ReadLines(file1);// LINQ Read Lines
 | |
| 			IEnumerable<string> lines2 = File.ReadLines(file2);// LINQ Read Lines
 | |
| 			lines1 = AddItemIDs(lines1);// LINQ Add ItemIDs to each line to make them unique
 | |
| 			lines2 = AddItemIDs(lines2);// LINQ Add ItemIDs to each line to make them unique
 | |
| 			// LINQ Lambda Expression - Only includes lines that contain the search text
 | |
| 			// Each line x such that local function Contains(tbsearch.Text, x) is true
 | |
| 			lines1 = lines1.Where<string>(x => Contains(tbSearch.Text, x));// LINQ Search
 | |
| 			lines2 = lines2.Where<string>(x => Contains(tbSearch.Text, x));// LINQ Search
 | |
| 			// Initialize Results
 | |
| 			lbResults1.Items.Clear();
 | |
| 			lbResults2.Items.Clear();
 | |
| 			// Initialize Procedure List
 | |
| 			lbProcedures.Items.Clear();
 | |
| 			// TODO: Are the following lines necessary
 | |
| 			string line1 = lines1.ElementAt<string>(0);
 | |
| 			string line2 = lines2.ElementAt<string>(0);
 | |
| 			// Load a List of Procedures
 | |
| 			MyProcs1 = FillProcedures(lines1);
 | |
| 			MyProcs2 = FillProcedures(lines2);
 | |
| 			// Populate the Procedure ListBox
 | |
| 			foreach (Procedure proc in MyProcs1)
 | |
| 			{
 | |
| 			// TODO: Is the following local variable necessary
 | |
| 				int i = lbProcedures.Items.Add(proc);
 | |
| 			}
 | |
| 			MyStatus = string.Format("{0} Procedures contain {1}",MyProcs1.Count(),tbSearch.Text);
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Fill the Procedure ListBox
 | |
| 		/// </summary>
 | |
| 		/// <param name="lines"></param>
 | |
| 		/// <returns></returns>
 | |
| 		private Procedures FillProcedures(IEnumerable<string> lines)
 | |
| 		{
 | |
| 			Procedures myProcs = new Procedures();
 | |
| 			string lastProc = null;
 | |
| 			int pageNumber = 0;
 | |
| 			foreach (string line in lines)
 | |
| 			{
 | |
| 				if (line.StartsWith("!!")) // !! Lines contain Procedure Info
 | |
| 				{
 | |
| 					lastProc = line;
 | |
| 					//Remember last Procedure line
 | |
| 					pageNumber = 1;
 | |
| 				}
 | |
| 				else if (line.StartsWith("Page Change from ")) // These lines contain Page Number 
 | |
| 				{
 | |
| 					pageNumber = int.Parse(line.Substring(line.LastIndexOf(' ')));
 | |
| 					// Remember last page number
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					// use remembered procedure and page number to save line of text 
 | |
| 					myProcs.Add(lastProc, pageNumber, line);// Otherwise add Procedure, Page or Line
 | |
| 				}
 | |
| 			}
 | |
| 			return myProcs;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// LINQ add ItemID Prefix to each line
 | |
| 		/// </summary>
 | |
| 		/// <param name="lines1"></param>
 | |
| 		/// <returns></returns>
 | |
| 		private static IEnumerable<string> AddItemIDs(IEnumerable<string> lines1)
 | |
| 		{
 | |
| 			List<string> list1 = new List<string>();
 | |
| 			string prefix = "";
 | |
| 			foreach (string line in lines1)
 | |
| 			{
 | |
| 				if (line.StartsWith("TX ")) //Get the ItemID
 | |
| 				{
 | |
| 					if (line.Contains("ItmID="))
 | |
| 					{
 | |
| 						prefix = line.Substring(line.IndexOf("ItmID=") + 6);
 | |
| 					}
 | |
| 					else
 | |
| 						prefix = "";
 | |
| 					list1.Add(line);
 | |
| 				}
 | |
| 				else if (line.Contains(" Atrbs: "))// Add the prefix to make the line unique
 | |
| 					list1.Add(prefix + line);
 | |
| 				else
 | |
| 				{
 | |
| 					prefix = "";
 | |
| 					list1.Add(line);
 | |
| 				}
 | |
| 			}
 | |
| 			lines1 = list1.AsEnumerable<string>();// Convert back to Enumerable to work with LINQ
 | |
| 			return lines1;
 | |
| 		}
 | |
| 		private string GetProcNum(string line)
 | |
| 		{
 | |
| 			string retval =  line.Substring(3, line.IndexOf(" | ") - 3);
 | |
| 			if (retval.Contains("_"))
 | |
| 				retval = retval.Substring(0, retval.IndexOf("_") - 1);
 | |
| 			return retval;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Include lines for Procedure or Page or Search is true
 | |
| 		/// Account for Case Insensitive CheckBox
 | |
| 		/// </summary>
 | |
| 		/// <param name="searchText"></param>
 | |
| 		/// <param name="x"></param>
 | |
| 		/// <returns></returns>
 | |
| 		private bool Contains(string searchText, string x)
 | |
| 		{
 | |
| 			bool result;
 | |
| 			if (cbCaseSensitive.Checked)
 | |
| 			{
 | |
| 				result = x.Contains(searchText) || x.StartsWith("Page Change from ") || Regex.IsMatch(x, @"^!![^|]+\|[^|]+?$", RegexOptions.Compiled);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				result = x.ToUpper().Contains(searchText.ToUpper()) || x.StartsWith("Page Change from ") || Regex.IsMatch(x, @"^!![^|]+\|[^|]+?$", RegexOptions.Compiled);
 | |
| 			}
 | |
| 			return result;
 | |
| 		}
 | |
| 		private void CompareContent(string file1, string file2)
 | |
| 		{
 | |
| 			// Enable the UltraCompare button
 | |
| 			// Collapse the Procedure Panel
 | |
| 			btnUC.Enabled = splitContainer3.Panel2Collapsed = true;
 | |
| 			IEnumerable<string> lines1 = FindFiles.ReadFilteredLines(file1, true, MyIgnore);
 | |
| 			IEnumerable<string> lines2 = FindFiles.ReadFilteredLines(file2, true, MyIgnore);
 | |
| 			IEnumerable<string> missing1 = lines1.Except<string>(lines2);
 | |
| 			IEnumerable<string> missing2 = lines2.Except<string>(lines1);
 | |
| 			lbResults1.Items.Clear();
 | |
| 			lbResults1.Items.AddRange(missing1.ToArray<string>());
 | |
| 			lbResults2.Items.Clear(); 
 | |
| 			lbResults2.Items.AddRange(missing2.ToArray<string>());
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// LINQ Perform DebugMeta Comparison
 | |
| 		/// </summary>
 | |
| 		/// <param name="file1"></param>
 | |
| 		/// <param name="file2"></param>
 | |
| 		private void CompareContent3(string file1, string file2)
 | |
| 		{
 | |
| 			// Disble the UltraCompare button
 | |
| 			// Expand the Procedure Panel
 | |
| 			btnUC.Enabled = splitContainer3.Panel2Collapsed = false;
 | |
| 			IEnumerable<string> lines1 = FindFiles.ReadFilteredLines(file1, true,MyIgnore);// LINQ Read lines excluding lines to be ignored
 | |
| 			IEnumerable<string> lines2 = FindFiles.ReadFilteredLines(file2, true, MyIgnore);// LINQ Read lines excluding lines to be ignored
 | |
| 			lines1 = AddItemIDs(lines1);// LINQ Add ItemID prefix to make lines unique
 | |
| 			lines2 = AddItemIDs(lines2);// LINQ Add ItemID prefix to make lines unique
 | |
| 			// The following lines create a list of lines without Page Numbers or procedures
 | |
| 			// They are removed from this list so that they will not be impacted by the intersect below
 | |
| 			IEnumerable<string> noPageNumbers1 = lines1.Where<string>(x => x.StartsWith("Page Change from ") == false);// LINQ get lines without Page Numbers
 | |
| 			IEnumerable<string> noPageNumbers2 = lines2.Where<string>(x => x.StartsWith("Page Change from ") == false);// LINQ get lines without Page Numbers
 | |
| 			noPageNumbers1 = noPageNumbers1.Where<string>(x => x.StartsWith("!! ") == false);//LINQ remove lines with !!
 | |
| 			noPageNumbers2 = noPageNumbers2.Where<string>(x => x.StartsWith("!! ") == false);//LINQ remove lines with !!
 | |
| 			IEnumerable<string> intersect = noPageNumbers1.Intersect<string>(noPageNumbers2);//LINQ find Matchhing lines
 | |
| 			List<string> lIntersect = intersect.ToList<string>();//LINQ Create a list of matching lines
 | |
| 			HashSet<string> hs = new HashSet<string>(intersect);// LINQ Create a HashSet of matching lines
 | |
| 			IEnumerable<string> missing1 = lines1.Where<string>(x => !hs.Contains<string>(x));// LINQ Remove matching lines
 | |
| 			IEnumerable<string> missing2 = lines2.Where<string>(x => !hs.Contains<string>(x));// LINQ Remove matching lines
 | |
| 			MyProcs1 = FillProcedures(missing1);// Fill Procedures from the lines that don't match (including Procedure and Page Number lines)
 | |
| 			MyProcs2 = FillProcedures(missing2);// Fill Procedures from the lines that don't match (including Procedure and Page Number lines)
 | |
| 			if (MyProcs1 != null && MyProcs1.Count > 0)// Fill Procedure ListBox with MyProcs1
 | |
| 			{
 | |
| 				foreach (Procedure proc in MyProcs1)
 | |
| 					lbProcedures.Items.Add(proc);
 | |
| 				MyStatus = string.Format("{0} Procedures found with differences", MyProcs1.Count());
 | |
| 			}
 | |
| 			else if (MyProcs2 != null && MyProcs2.Count > 0)// Fill Procedure ListBox with MyProcs1
 | |
| 			{
 | |
| 				foreach (Procedure proc in MyProcs2)
 | |
| 					lbProcedures.Items.Add(proc);
 | |
| 				MyStatus = string.Format("{0} Procedures found with differences", MyProcs2.Count());
 | |
| 			}
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Open One or more PDF's
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void lbResults1_SelectedIndexChanged(object sender, EventArgs e)
 | |
| 		{
 | |
| 			string line=null;
 | |
| 			if (lbResults1.SelectedItem is string)
 | |
| 				line = (string)lbResults1.SelectedItem;
 | |
| 			Line myLine = lbResults1.SelectedItem as Line;
 | |
| 				switch (myLast)
 | |
| 				{
 | |
| 					case LastWas.Pagination:
 | |
| 						line = OpenPDF(line);
 | |
| 						break;
 | |
| 					case LastWas.Baseline: // TODO: Need to add code here to open matching file
 | |
| 						OpenOnePDF(myLine,1);
 | |
| 						break;
 | |
| 					case LastWas.Search: // TODO: Need to add code here to open matching file
 | |
| 						OpenOnePDF(myLine,1);
 | |
| 						break;
 | |
| 					default:
 | |
| 						break;
 | |
| 				}
 | |
| 		}
 | |
| 		private void lbResults2_SelectedIndexChanged(object sender, EventArgs e)
 | |
| 		{
 | |
| 
 | |
| 			string line=null;
 | |
| 			if(lbResults2.SelectedItem is string)
 | |
| 				line = (string)lbResults2.SelectedItem;
 | |
| 			Line myLine = lbResults2.SelectedItem as Line;
 | |
| 
 | |
| 			switch (myLast)
 | |
| 			{
 | |
| 				case LastWas.Pagination:
 | |
| 					line = OpenPDF(line);
 | |
| 					break;
 | |
| 				case LastWas.Baseline: // TODO: Need to add code here to open matching file
 | |
| 					OpenOnePDF(myLine,2);
 | |
| 					break;
 | |
| 				case LastWas.Search: // TODO: Need to add code here to open matching file
 | |
| 					OpenOnePDF(myLine,2);
 | |
| 					break;
 | |
| 				default:
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 		string exePath;
 | |
| 		private string OpenPDF(string line)
 | |
| 		{
 | |
| 			int page = int.Parse(line.Substring(0, 6));
 | |
| 			// B2018-113 - Replace slashes and backslashes with underscores just as PROMS does when creating a PDF file.
 | |
| 			line = line.Substring(8, line.IndexOf(".S") - 8).Replace("/", "_").Replace("\\", "_");
 | |
| 			FindFile ff = lbDifferent.SelectedItem as FindFile;
 | |
| 			FileInfo fi1 = new FileInfo(ff.File1);
 | |
| 			FileInfo fi2 = new FileInfo(ff.File2);
 | |
| 			// If you don't know where the Reader executable is for PDFs Open a PDF and Check to see where the path points
 | |
| 			if (exePath == null)
 | |
| 			{
 | |
| 				System.Diagnostics.Process p = System.Diagnostics.Process.Start(fi1.DirectoryName + "\\" + line + ".pdf");
 | |
| 				exePath = TryToGetPath(p);
 | |
| 				p.Kill(); // No need to keep it open
 | |
| 			}
 | |
| 			// Open the first PDF on a Specific Page
 | |
| 			System.Diagnostics.ProcessStartInfo psi1 = new System.Diagnostics.ProcessStartInfo(exePath, string.Format("/A page={0} ", page) + fi1.DirectoryName + "\\" + line + ".pdf ");
 | |
| 			System.Diagnostics.Process p1 = System.Diagnostics.Process.Start(psi1);
 | |
| 			// Move the PDF Reader window to 0,0
 | |
| 			MoveProcess(p1, 0, 0);
 | |
| 			// Open the first PDF on a Specific Page
 | |
| 			System.Diagnostics.ProcessStartInfo psi2 = new System.Diagnostics.ProcessStartInfo(exePath, string.Format("/A page={0} ", page) + fi2.DirectoryName + "\\" + line + ".pdf ");
 | |
| 			System.Diagnostics.Process p2 = System.Diagnostics.Process.Start(psi2);
 | |
| 			// Move the PDF Reader window to 960,0
 | |
| 			// TODO: This Offset could be a Setting
 | |
| 			MoveProcess(p2, 960, 0);
 | |
| 			return line;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Try to get the location of the PDF Reader executable
 | |
| 		/// </summary>
 | |
| 		/// <param name="p">Process of PDF Reader</param>
 | |
| 		/// <returns></returns>
 | |
| 		private string TryToGetPath(System.Diagnostics.Process p)
 | |
| 		{
 | |
| 			p.WaitForInputIdle();
 | |
| 			while (p.MainModule == null)
 | |
| 			{
 | |
| 				Console.WriteLine("{0} -  {1}", p.MainWindowTitle,p.ProcessName);
 | |
| 				p.WaitForInputIdle();
 | |
| 				Application.DoEvents();
 | |
| 			}
 | |
| 			return p.MainModule.FileName;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Start UltraCompare of two files
 | |
| 		/// </summary>
 | |
| 		/// <param name="compareFile"></param>
 | |
| 		/// <param name="baseFile"></param>
 | |
| 		private void CompareOneFile(string compareFile, string baseFile)
 | |
| 		{
 | |
| 			//Console.WriteLine("Compare {0} and {1}", compareFile, baseFile);
 | |
| 			string progname = string.Empty;
 | |
| 			if (System.IO.File.Exists(@"C:\Program Files\IDM Computer Solutions\UltraCompare\UC.exe"))
 | |
| 				progname = @"C:\Program Files\IDM Computer Solutions\UltraCompare\UC.exe";
 | |
| 			if (System.IO.File.Exists(@"C:\Program Files (x86)\IDM Computer Solutions\UltraCompare\UC.exe"))
 | |
| 				progname = @"C:\Program Files (x86)\IDM Computer Solutions\UltraCompare\UC.exe";
 | |
| 			System.Diagnostics.ProcessStartInfo psi =
 | |
| 				new System.Diagnostics.ProcessStartInfo(progname, string.Format(@" -t ""{0}"" ""{1}""", compareFile, baseFile));
 | |
| 			System.Diagnostics.Process prc = System.Diagnostics.Process.Start(psi);
 | |
| 		}
 | |
| 
 | |
| 		private ProcessLocationQueue myQueue= new ProcessLocationQueue();
 | |
| 		private Timer queueTimer = null;
 | |
| 		/// <summary>
 | |
| 		/// Move a Process to a specific screen location - This is done with a timer so 
 | |
| 		/// that it waits until windows are finished being initialized.
 | |
| 		/// </summary>
 | |
| 		/// <param name="proc"></param>
 | |
| 		/// <param name="x"></param>
 | |
| 		/// <param name="y"></param>
 | |
| 		private void MoveProcess(System.Diagnostics.Process proc, int x, int y)
 | |
| 		{
 | |
| 			if (queueTimer == null)
 | |
| 			{
 | |
| 				queueTimer = new Timer();
 | |
| 				queueTimer.Enabled = false;
 | |
| 				queueTimer.Tick += queueTimer_Tick;
 | |
| 				queueTimer.Interval = 1000;
 | |
| 			}
 | |
| 			myQueue.Add(proc, x, y);
 | |
| 			if (!queueTimer.Enabled) 
 | |
| 				queueTimer.Enabled = true;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// timer tick for moving a process window
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		void queueTimer_Tick(object sender, EventArgs e)
 | |
| 		{
 | |
| 			while (myQueue.Count > 0)
 | |
| 				myQueue.ProcessNext();
 | |
| 				queueTimer.Enabled = false;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Open PDF associated with the selected line
 | |
| 		/// </summary>
 | |
| 		/// <param name="myLine"></param>
 | |
| 		/// <param name="list"></param>
 | |
| 		private void OpenOnePDF(Line myLine, int list)
 | |
| 		{
 | |
| 			// B2018-113 - Replace slashes and backslashes with underscores just as PROMS does when creating a PDF file.
 | |
| 			string proc = myLine.MyProc.Number.Replace("/","_").Replace("\\","_");
 | |
| 			int pagenum = myLine.MyPage.Number;
 | |
| 			FindFile ff = lbDifferent.SelectedItem as FindFile;
 | |
| 			FileInfo fi1 = new FileInfo(ff.File1);
 | |
| 			FileInfo fi2 = new FileInfo(ff.File2);
 | |
| 			if (exePath == null)
 | |
| 			{
 | |
| 				System.Diagnostics.Process p = System.Diagnostics.Process.Start(fi1.DirectoryName + "\\" + proc + ".pdf");
 | |
| 				while (exePath == null)
 | |
| 				{
 | |
| 					try
 | |
| 					{
 | |
| 
 | |
| 						exePath = p.MainModule.FileName;
 | |
| 					}
 | |
| 					catch (Exception ex)
 | |
| 					{
 | |
| 						Application.DoEvents();
 | |
| 						Console.WriteLine("{0} - {1}", ex.GetType().Name, ex.Message);
 | |
| 					}
 | |
| 				}
 | |
| 				p.Kill();
 | |
| 			}
 | |
| 			if (list == 1)
 | |
| 			{
 | |
| 				System.Diagnostics.ProcessStartInfo psi1 = new System.Diagnostics.ProcessStartInfo(exePath, string.Format("/A page={0} ", pagenum) + fi1.DirectoryName + "\\" + proc + ".pdf ");
 | |
| 				System.Diagnostics.Process p1 = System.Diagnostics.Process.Start(psi1);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				System.Diagnostics.ProcessStartInfo psi2 = new System.Diagnostics.ProcessStartInfo(exePath, string.Format("/A page={0} ", pagenum) + fi2.DirectoryName + "\\" + proc + ".pdf ");
 | |
| 				System.Diagnostics.Process p1 = System.Diagnostics.Process.Start(psi2);
 | |
| 			}
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Perform Debug Meta file comparison for all of the folders within the automated testing folders 
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void btnBaseline_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			myLast = LastWas.Baseline;
 | |
| 			lbDifferent.DataSource = null;
 | |
| 			// Initialize Differnce and Results ListBoxes
 | |
| 			lbDifferent.Items.Clear();
 | |
| 			lbResults1.Items.Clear();
 | |
| 			lbResults2.Items.Clear();
 | |
| 			MyStatus = "Searching...";
 | |
| 			// Perform code to find DebugMeta files with diffences
 | |
| 			FindFiles fnd = new FindFiles(cbFile1.Text, cbFile2.Text, "DebugMeta.txt",MyIgnore);
 | |
| 			lbDifferent.DataSource = fnd;
 | |
| 			lbDifferent.DisplayMember = "File1";
 | |
| 			MyStatus = string.Format("{0} Differences Found", fnd.Count);
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Perform search of all the DocVersions Debug.Meta Files
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void btnSearch_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			// Disble the UltraCompare button
 | |
| 			// Expand the Procedure Panel
 | |
| 			btnUC.Enabled= splitContainer3.Panel2Collapsed = false;
 | |
| 			myLast = LastWas.Search;
 | |
| 			// Initialize ListBoxes
 | |
| 			lbDifferent.DataSource = null;
 | |
| 			lbDifferent.Items.Clear();
 | |
| 			lbResults1.Items.Clear();
 | |
| 			lbResults2.Items.Clear();
 | |
| 			MyStatus = "Searching...";
 | |
| 			//Perform Search
 | |
| 			FindFiles fnd = new FindFiles(cbFile1.Text, cbFile2.Text, "DebugMeta.txt", tbSearch.Text, SearchType.Contains, cbCaseSensitive.Checked);
 | |
| 			lbDifferent.DataSource = fnd;
 | |
| 			lbDifferent.DisplayMember = "File1";
 | |
| 			MyStatus = string.Format("{0} Differences Found", fnd.Count);
 | |
| 		}
 | |
| 		bool InHandler1 = false;
 | |
| 		// Track changes to the File Path 1 including Most Recent Used
 | |
| 		private void cbFile1_TextChanged(object sender, EventArgs e)
 | |
| 		{
 | |
| 			if (InHandler1) return;
 | |
| 			InHandler1 = true;
 | |
| 			string str = cbFile1.Text;
 | |
| 			while (cbFile1.Items.Contains(str))
 | |
| 				cbFile1.Items.Remove(str);
 | |
| 			cbFile1.Items.Insert(0, str);
 | |
| 			cbFile1.SelectedIndex = 0;
 | |
| 			Properties.Settings.Default.MRU1 = new System.Collections.Specialized.StringCollection();
 | |
| 			foreach (string str1 in cbFile1.Items)
 | |
| 				Properties.Settings.Default.MRU1.Add(str1);
 | |
| 			Properties.Settings.Default.Save();
 | |
| 			InHandler1 = false;
 | |
| 		}
 | |
| 		bool InHandler2 = false;
 | |
| 		// Track changes to the File Path 2 including Most Recent Used
 | |
| 		private void cbFile2_TextChanged(object sender, EventArgs e)
 | |
| 		{
 | |
| 			if (InHandler2) return;
 | |
| 			InHandler2 = true;
 | |
| 			string str = cbFile2.Text;
 | |
| 			while (cbFile2.Items.Contains(str))
 | |
| 				cbFile2.Items.Remove(str);
 | |
| 			cbFile2.Items.Insert(0, str);
 | |
| 			cbFile2.SelectedIndex = 0;
 | |
| 			Properties.Settings.Default.MRU2 = new System.Collections.Specialized.StringCollection();
 | |
| 			foreach (string str2 in cbFile2.Items)
 | |
| 				Properties.Settings.Default.MRU2.Add(str2);
 | |
| 			Properties.Settings.Default.Save();
 | |
| 			InHandler2 = false;
 | |
| 		}
 | |
| 		private void lbProcedures_SelectedIndexChanged(object sender, EventArgs e)
 | |
| 		{
 | |
| 			//Initialize Results List Box
 | |
| 			lbResults1.Items.Clear();
 | |
| 			Procedure myProc = lbProcedures.SelectedItem as Procedure;
 | |
| 			//TODO: May need to consider if there are duplicate procedure numers and titles
 | |
| 			Procedure myProc1 = MyProcs1.Find(x => x.Number == myProc.Number && x.Title == myProc.Title);
 | |
| 			// Build the results ListBox for the left window
 | |
| 			if (myProc1 != null)
 | |
| 			{
 | |
| 				foreach (Page myPage in myProc1.MyPages)
 | |
| 				{
 | |
| 					lbResults1.Items.Add(myPage);
 | |
| 					foreach (Line myLine in myPage.MyLines)
 | |
| 						lbResults1.Items.Add(myLine);
 | |
| 				}
 | |
| 			}
 | |
| 			lbResults2.Items.Clear();
 | |
| 			// Build the results ListBox for the right window
 | |
| 			Procedure myProc2 = MyProcs2.Find(x => x.Number == myProc.Number && x.Title == myProc.Title);
 | |
| 			if (myProc2 != null)
 | |
| 			{
 | |
| 				foreach (Page myPage in myProc2.MyPages)
 | |
| 				{
 | |
| 					lbResults2.Items.Add(myPage);
 | |
| 					foreach (Line myLine in myPage.MyLines)
 | |
| 						lbResults2.Items.Add(myLine);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Open Ultra Compare for the currently selected DocVersion
 | |
| 		/// </summary>
 | |
| 		/// <param name="sender"></param>
 | |
| 		/// <param name="e"></param>
 | |
| 		private void btnUC_Click(object sender, EventArgs e)
 | |
| 		{
 | |
| 			if (myLast == LastWas.Pagination)
 | |
| 			{
 | |
| 				FindFile ff = lbDifferent.SelectedItem as FindFile;
 | |
| 				CompareOneFile(ff.File1, ff.File2);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	public	enum SearchType
 | |
| 		{
 | |
| 			Contains,
 | |
| 			StartsWith,
 | |
| 			EndsWith
 | |
| 		};
 | |
| 	public class Settings
 | |
| 	{
 | |
| 		private BindingList<string> _IgnoreLines;
 | |
| 		public BindingList<string> IgnoreLines
 | |
| 		{
 | |
| 			get { return _IgnoreLines; }
 | |
| 			set { _IgnoreLines = value; }
 | |
| 		}
 | |
| 	}
 | |
| 	public partial class FindFile
 | |
| 	{
 | |
| 		private string _File1;
 | |
| 		public string File1
 | |
| 		{
 | |
| 			get { return _File1; }
 | |
| 			set { _File1 = value; }
 | |
| 		}
 | |
| 		private string _File2;
 | |
| 		public string File2
 | |
| 		{
 | |
| 			get { return _File2; }
 | |
| 			set { _File2 = value; }
 | |
| 		}
 | |
| 		public FindFile(string file1, string file2)
 | |
| 		{
 | |
| 			File1 = file1;
 | |
| 			File2 = file2;
 | |
| 		}
 | |
| 	}
 | |
| 	public partial class FindFiles : List<FindFile>
 | |
| 	{
 | |
| 		private string _FileName;
 | |
| 		public string FileName
 | |
| 		{
 | |
| 			get { return _FileName; }
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Build list of DocVersion Folders with differences
 | |
| 		/// </summary>
 | |
| 		/// <param name="path1">Base path</param>
 | |
| 		/// <param name="path2">Compare path</param>
 | |
| 		/// <param name="fileName">filename</param>
 | |
| 		/// <param name="myIgnore">Ignore list</param>
 | |
| 		public FindFiles(string path1, string path2, string fileName,IgnoreLines myIgnore)
 | |
| 		{
 | |
| 			DirectoryInfo di1 = new DirectoryInfo(path1);
 | |
| 			DirectoryInfo di2 = new DirectoryInfo(path2);
 | |
| 			_FileName = fileName;
 | |
| 			FillByCompare(di1, di2, fileName, myIgnore);
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Fill for a search
 | |
| 		/// </summary>
 | |
| 		/// <param name="path1"></param>
 | |
| 		/// <param name="path2"></param>
 | |
| 		/// <param name="fileName"></param>
 | |
| 		/// <param name="searchText"></param>
 | |
| 		/// <param name="searchType"></param>
 | |
| 		/// <param name="caseSensitive"></param>
 | |
| 		public FindFiles(string path1, string path2, string fileName, string searchText, SearchType searchType, bool caseSensitive)
 | |
| 		{
 | |
| 			DirectoryInfo di1 = new DirectoryInfo(path1);
 | |
| 			DirectoryInfo di2 = new DirectoryInfo(path2);
 | |
| 			_FileName = fileName;
 | |
| 			FillByCompare(di1, di2, fileName,searchText,searchType, caseSensitive);
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Fill results by search
 | |
| 		/// </summary>
 | |
| 		/// <param name="di1"></param>
 | |
| 		/// <param name="di2"></param>
 | |
| 		/// <param name="fileName"></param>
 | |
| 		/// <param name="searchText"></param>
 | |
| 		/// <param name="searchType"></param>
 | |
| 		/// <param name="caseSensitive"></param>
 | |
| 		private void FillByCompare(DirectoryInfo di1, DirectoryInfo di2, string fileName, string searchText, SearchType searchType, bool caseSensitive)
 | |
| 		{
 | |
| 			foreach (DirectoryInfo diChild1 in di1.GetDirectories())
 | |
| 			{
 | |
| 				DirectoryInfo diChild2 = new DirectoryInfo(di2.FullName + "\\" + diChild1.Name);
 | |
| 				if (diChild2.Exists)
 | |
| 					FillByCompare(diChild1, diChild2, fileName,searchText,searchType,caseSensitive);
 | |
| 			}
 | |
| 			foreach (FileInfo fiChild1 in di1.GetFiles(fileName))
 | |
| 			{
 | |
| 				FileInfo fiChild2 = new FileInfo(di2.FullName + "\\" + fiChild1.Name);
 | |
| 				if (fiChild2.Exists)
 | |
| 				{
 | |
| 					if (CompareFile(fiChild1, fiChild2,searchText,searchType, caseSensitive))
 | |
| 						Add(new FindFile(fiChild1.FullName, fiChild2.FullName));
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		///  LINQ Peform Searc on DebugMeta files in all DocVersion folders
 | |
| 		/// </summary>
 | |
| 		/// <param name="fiChild1"></param>
 | |
| 		/// <param name="fiChild2"></param>
 | |
| 		/// <param name="searchText"></param>
 | |
| 		/// <param name="searchType"></param>
 | |
| 		/// <param name="caseSensitive"></param>
 | |
| 		/// <returns></returns>
 | |
| 		private bool CompareFile(FileInfo fiChild1, FileInfo fiChild2, string searchText, SearchType searchType,bool caseSensitive)
 | |
| 		{
 | |
| 			IEnumerable<string> lines1=null;
 | |
| 			IEnumerable<string> lines2=null;
 | |
| 			switch (searchType)
 | |
| 			{
 | |
| 				case SearchType.Contains:
 | |
| 					if (caseSensitive)
 | |
| 					{
 | |
| 						lines1 = File.ReadLines(fiChild1.FullName).Where<string>(x => x.Contains(searchText));
 | |
| 						lines2 = File.ReadLines(fiChild2.FullName).Where<string>(x => x.Contains(searchText));
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						lines1 = File.ReadLines(fiChild1.FullName).Where<string>(x => x.ToUpper().Contains(searchText.ToUpper()));
 | |
| 						lines2 = File.ReadLines(fiChild2.FullName).Where<string>(x => x.ToUpper().Contains(searchText.ToUpper()));
 | |
| 					}
 | |
| 					break;
 | |
| 				case SearchType.StartsWith:
 | |
| 					if (caseSensitive)
 | |
| 					{
 | |
| 						lines1 = File.ReadLines(fiChild1.FullName).Where<string>(x => x.StartsWith(searchText));
 | |
| 						lines2 = File.ReadLines(fiChild2.FullName).Where<string>(x => x.StartsWith(searchText));
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						lines1 = File.ReadLines(fiChild1.FullName).Where<string>(x => x.ToUpper().StartsWith(searchText.ToUpper()));
 | |
| 						lines2 = File.ReadLines(fiChild2.FullName).Where<string>(x => x.ToUpper().StartsWith(searchText.ToUpper()));
 | |
| 					}
 | |
| 					break;
 | |
| 				case SearchType.EndsWith:
 | |
| 					if (caseSensitive)
 | |
| 					{
 | |
| 						lines1 = File.ReadLines(fiChild1.FullName).Where<string>(x => x.EndsWith(searchText));
 | |
| 						lines2 = File.ReadLines(fiChild2.FullName).Where<string>(x => x.EndsWith(searchText));
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						lines1 = File.ReadLines(fiChild1.FullName).Where<string>(x => x.ToUpper().EndsWith(searchText.ToUpper()));
 | |
| 						lines2 = File.ReadLines(fiChild2.FullName).Where<string>(x => x.ToUpper().EndsWith(searchText.ToUpper()));
 | |
| 					}
 | |
| 					break;
 | |
| 			}
 | |
| 			if (lines1 != null && lines2 != null)
 | |
| 			{
 | |
| 				if ((lines1.Count<string>() > 0) || (lines2.Count<string>() > 0))
 | |
| 				{
 | |
| 					return true;
 | |
| 				}
 | |
| 				return false;
 | |
| 			}
 | |
| 			return false;
 | |
| 		}
 | |
| 		private void FillByCompare(DirectoryInfo di1, DirectoryInfo di2, string fileName, IgnoreLines myIgnore)
 | |
| 		{
 | |
| 			foreach (DirectoryInfo diChild1 in di1.GetDirectories())
 | |
| 			{
 | |
| 				DirectoryInfo diChild2 = new DirectoryInfo(di2.FullName + "\\" + diChild1.Name);
 | |
| 				if (diChild2.Exists)
 | |
| 					FillByCompare(diChild1, diChild2, fileName,myIgnore);// Recursively work on Sub-Folders
 | |
| 			}
 | |
| 			foreach (FileInfo fiChild1 in di1.GetFiles(fileName))
 | |
| 			{
 | |
| 				FileInfo fiChild2 = new FileInfo(di2.FullName + "\\" + fiChild1.Name);
 | |
| 				if (fiChild2.Exists)
 | |
| 				{
 | |
| 					if (CompareFile(fiChild1, fiChild2,myIgnore))
 | |
| 						Add(new FindFile(fiChild1.FullName, fiChild2.FullName));// Process Each File
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		private bool CompareFile(FileInfo fiChild1, FileInfo fiChild2,IgnoreLines myIgnore)
 | |
| 		{
 | |
| 			if (fiChild1.Name == "DebugMeta.txt")
 | |
| 			{
 | |
| 				IEnumerable<string> lines1 = ReadFilteredLines(fiChild1.FullName, false, myIgnore);//LINQ Read lines without ignored lines
 | |
| 				IEnumerable<string> lines2 = ReadFilteredLines(fiChild2.FullName, false, myIgnore);//LINQ Read lines without ignored lines
 | |
| 				if (lines1.Except<string>(lines2).Count<string>() == 0 &&
 | |
| 					lines2.Except<string>(lines1).Count<string>() == 0) //Look for lines in one file that are not in the other
 | |
| 					return false;
 | |
| 				return true;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				string file1Contents = ReadContents(fiChild1);// This is just a simple text comparison
 | |
| 				string file2Contents = ReadContents(fiChild2);
 | |
| 				return !file1Contents.Equals(file2Contents);
 | |
| 			}
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// LINQ - Readlines and remove items based upon the ignore list
 | |
| 		/// </summary>
 | |
| 		/// <param name="child1"></param>
 | |
| 		/// <param name="includeProcedures"></param>
 | |
| 		/// <param name="myIgnore"></param>
 | |
| 		/// <returns></returns>
 | |
| 		public static IEnumerable<string> ReadFilteredLines(string child1, bool includeProcedures, IgnoreLines myIgnore)
 | |
| 		{
 | |
| 			IEnumerable<string> lines = File.ReadLines(child1);
 | |
| 			lines = lines.Where<string>(x => FindProcedure(x,includeProcedures));
 | |
| 			foreach (IgnoreLine ignore in myIgnore)
 | |
| 			{
 | |
| 				if (ignore.Active)
 | |
| 				{
 | |
| 					switch (ignore.SearchType)
 | |
| 					{
 | |
| 						case Relation.Contains:
 | |
| 							lines = lines.Where<string>(x => x.Contains(ignore.Text) == false);
 | |
| 							break;
 | |
| 						case Relation.StartsWith:
 | |
| 							lines = lines.Where<string>(x => x.StartsWith(ignore.Text) == false);
 | |
| 							break;
 | |
| 						case Relation.EndsWith:
 | |
| 							lines = lines.Where<string>(x => x.EndsWith(ignore.Text) == false);
 | |
| 							break;
 | |
| 						case Relation.Regex:
 | |
| 							Regex myreg = new Regex(ignore.Text, RegexOptions.Compiled);
 | |
| 							lines = lines.Where<string>(x => myreg.IsMatch(x) == false);
 | |
| 							break;
 | |
| 						default:
 | |
| 							break;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 			return lines;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// Find a procedure line in a meta file
 | |
| 		/// </summary>
 | |
| 		/// <param name="x"></param>
 | |
| 		/// <param name="includeProcedures"></param>
 | |
| 		/// <returns></returns>
 | |
| 		private static bool FindProcedure(string x, bool includeProcedures)
 | |
| 		{
 | |
| 			bool result = x.StartsWith("!!") == false;
 | |
| 			if(includeProcedures) result |= Regex.IsMatch(x, @"^!![^|]+\|[^|]+?$", RegexOptions.Compiled);
 | |
| 			return result;
 | |
| 		}
 | |
| 		/// <summary>
 | |
| 		/// basic text read
 | |
| 		/// </summary>
 | |
| 		/// <param name="fiChild1"></param>
 | |
| 		/// <returns></returns>
 | |
| 		private string ReadContents(FileInfo fiChild1)
 | |
| 		{
 | |
| 			StreamReader sr = fiChild1.OpenText();
 | |
| 			string buff = sr.ReadToEnd();
 | |
| 			return buff;
 | |
| 		}
 | |
| 	}
 | |
| 	// Classes for structured data storage used for meta file comparisons
 | |
| 	//
 | |
| 	// Procedure contains:
 | |
| 	// Number - Procedure Number
 | |
| 	// Title - Procedure Title
 | |
| 	// MyPages - The Page objects associated with this procedure
 | |
| 	//
 | |
| 	// Page contains:
 | |
| 	// Number - PageNumber
 | |
| 	// MyLines - The Line Objects associated with this Page
 | |
| 	//
 | |
| 	// Line contains:
 | |
| 	// MyProc - The containing procedure
 | |
| 	// MyPage - the containing page
 | |
| 	// Text - the line of text
 | |
| 	public partial class Procedure
 | |
| 	{
 | |
| 		private string _Number;
 | |
| 		public string Number
 | |
| 		{
 | |
| 			get { return _Number; }
 | |
| 			set { _Number = value; }
 | |
| 		}
 | |
| 		private string _Title;
 | |
| 		public string Title
 | |
| 		{
 | |
| 			get { return _Title; }
 | |
| 			set { _Title = value; }
 | |
| 		}
 | |
| 		private Pages _MyPages = new Pages();
 | |
| 		public Pages MyPages
 | |
| 		{
 | |
| 			get { return _MyPages; }
 | |
| 			set { _MyPages = value; }
 | |
| 		}
 | |
| 		public Procedure(string number, string title)
 | |
| 		{
 | |
| 			_Number = number;
 | |
| 			_Title = title;
 | |
| 		}
 | |
| 		public override string ToString()
 | |
| 		{
 | |
| 			return string.Format("{0} - {1}", Number, Title);
 | |
| 		}
 | |
| 	}
 | |
| 	public partial class Procedures : List<Procedure>
 | |
| 	{
 | |
| 		// Sample data for a Procedure Number line
 | |
| 		// !! E-0 | Reactor Trip Or Safety Injection
 | |
| 		// The First Group is the Procedure Number
 | |
| 		// The Second Group is the Procedure Title
 | |
| 		public Regex parseLine = new Regex("^!! (.*) \\| (.*)$", RegexOptions.Compiled);
 | |
| 		/// <summary>
 | |
| 		/// This adds a procedure, page and line class as needed, If the procedure
 | |
| 		/// already exists it is used.  If the page already exists it is used.
 | |
| 		/// </summary>
 | |
| 		/// <param name="lastProc">Procedure Line matches Regular Expression above</param>
 | |
| 		/// <param name="pageNumber">Page Number</param>
 | |
| 		/// <param name="text">Text from the meta File</param>
 | |
| 		public void Add(string lastProc, int pageNumber, string text)
 | |
| 		{
 | |
| 			if (lastProc == null) return;
 | |
| 			Match m = parseLine.Match(lastProc);
 | |
| 			if (m.Success)
 | |
| 			{
 | |
| 				Procedure myProc = this.Find(x => x.Number.Equals(m.Groups[1].ToString()) && x.Title.Equals(m.Groups[2].ToString()));
 | |
| 				if (myProc == null) this.Add(myProc = new Procedure(m.Groups[1].ToString(), m.Groups[2].ToString()));
 | |
| 				Page myPage = myProc.MyPages.Find(x => x.Number == pageNumber);
 | |
| 				if (myPage == null) myProc.MyPages.Add(myPage = new Page(pageNumber));
 | |
| 				myPage.MyLines.Add(new Line(text, myProc, myPage));
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	public partial class Page
 | |
| 	{
 | |
| 		private int _Number;
 | |
| 		public int Number
 | |
| 		{
 | |
| 			get { return _Number; }
 | |
| 			set { _Number = value; }
 | |
| 		}
 | |
| 		private Lines _MyLines = new Lines();
 | |
| 
 | |
| 		public Lines MyLines
 | |
| 		{
 | |
| 			get { return _MyLines; }
 | |
| 			set { _MyLines = value; }
 | |
| 		}
 | |
| 		public Page(int number)
 | |
| 		{
 | |
| 			_Number = number;
 | |
| 		}
 | |
| 		public override string ToString()
 | |
| 		{
 | |
| 			return string.Format("Page {0}", Number);
 | |
| 		}
 | |
| 	}
 | |
| 	public partial class Pages : List<Page>
 | |
| 	{
 | |
| 		public void Add(int number)
 | |
| 		{
 | |
| 			Add(new Page(number));
 | |
| 		}
 | |
| 	}
 | |
| 	public partial class Line
 | |
| 	{
 | |
| 		private Procedure _MyProc;
 | |
| 		public Procedure MyProc
 | |
| 		{
 | |
| 			get { return _MyProc; }
 | |
| 			set { _MyProc = value; }
 | |
| 		}
 | |
| 		private Page _MyPage;
 | |
| 		public Page MyPage
 | |
| 		{
 | |
| 			get { return _MyPage; }
 | |
| 			set { _MyPage = value; }
 | |
| 		}
 | |
| 		private string _Text;
 | |
| 		public string Text
 | |
| 		{
 | |
| 			get { return _Text; }
 | |
| 			set { _Text = value; }
 | |
| 		}
 | |
| 		public Line(string text)
 | |
| 		{
 | |
| 			_Text = text;
 | |
| 		}
 | |
| 		public Line(string text, Procedure myProc, Page myPage)
 | |
| 		{
 | |
| 			_Text = text;
 | |
| 			_MyProc = myProc;
 | |
| 			_MyPage = myPage;
 | |
| 		}
 | |
| 		public override string ToString()
 | |
| 		{
 | |
| 			return Text;
 | |
| 		}
 | |
| 	}
 | |
| 	public partial class Lines : List<Line>
 | |
| 	{
 | |
| 		public void Add(string text)
 | |
| 		{
 | |
| 			Add(new Line(text));
 | |
| 		}
 | |
| 	}
 | |
| 	[Serializable]
 | |
| 	public partial class IgnoreLine
 | |
| 	{
 | |
| 		private bool _Active = true;
 | |
| 		public bool Active
 | |
| 		{
 | |
| 			get { return _Active; }
 | |
| 			set { _Active = value; }
 | |
| 		}
 | |
| 		private Relation _SearchType = Relation.Contains;
 | |
| 		public Relation SearchType
 | |
| 		{
 | |
| 			get { return _SearchType; }
 | |
| 			set { _SearchType = value; }
 | |
| 		}
 | |
| 		private string _Text;
 | |
| 		public string Text
 | |
| 		{
 | |
| 			get { return _Text; }
 | |
| 			set { _Text = value; }
 | |
| 		}
 | |
| 		public IgnoreLine(string text, Relation searchType, bool active)
 | |
| 		{
 | |
| 			Text = text;
 | |
| 			SearchType = searchType;
 | |
| 			Active = active;
 | |
| 		}
 | |
| 		public IgnoreLine()
 | |
| 		{
 | |
| 		}
 | |
| 	}
 | |
| 	[Serializable]
 | |
| 	public partial class IgnoreLines : BindingList<IgnoreLine>
 | |
| 	{
 | |
| 		public IgnoreLines()
 | |
| 		{
 | |
| 		}
 | |
| 		public void Add(string text, Relation searchType, bool active)
 | |
| 		{
 | |
| 			Add(new IgnoreLine(text, searchType, active));
 | |
| 		}
 | |
| 		// Convert IgnoreLines to string (XML)
 | |
| 		public override string ToString()
 | |
| 		{
 | |
| 			return GenericSerializer<IgnoreLines>.StringSerialize(this);
 | |
| 		}
 | |
| 		// Convert string to IgnoreLines
 | |
| 		public static IgnoreLines Get(string xml)
 | |
| 		{
 | |
| 			return GenericSerializer<IgnoreLines>.StringDeserialize(xml);
 | |
| 		}
 | |
| 	}
 | |
| 	/// <summary>
 | |
| 	/// This is a simple serializer that takes a class and converts it to and from string (XML)
 | |
| 	/// </summary>
 | |
| 	/// <typeparam name="T"></typeparam>
 | |
| 	public static class GenericSerializer<T> where T : class
 | |
| 	{
 | |
| 		public static string StringSerialize(T t)
 | |
| 		{
 | |
| 			string strOutput = string.Empty;
 | |
| 			XmlSerializer xs = new XmlSerializer(typeof(T));
 | |
| 			using (MemoryStream ms = new MemoryStream())
 | |
| 			{
 | |
| 				xs.Serialize(new NonXsiTextWriter(ms, Encoding.Unicode), t);
 | |
| 				//xs.Serialize(ms, t);
 | |
| 				ms.Position = 0;
 | |
| 				StreamReader sr = new StreamReader(ms);
 | |
| 				strOutput = sr.ReadToEnd();
 | |
| 				ms.Close();
 | |
| 			}
 | |
| 			return strOutput;
 | |
| 		}
 | |
| 		public static T StringDeserialize(string s)
 | |
| 		{
 | |
| 			T t;
 | |
| 			string ss = s.Replace("encoding=\"utf-16\"", "");
 | |
| 			XmlSerializer xs = new XmlSerializer(typeof(T));
 | |
| 			UTF8Encoding enc = new UTF8Encoding();
 | |
| 			Byte[] arrBytData = enc.GetBytes(ss);
 | |
| 			using (MemoryStream ms = new MemoryStream(arrBytData))
 | |
| 			{
 | |
| 				t = (T)xs.Deserialize(ms);
 | |
| 			}
 | |
| 			return t;
 | |
| 		}
 | |
| 	}
 | |
| 	/// <summary>
 | |
| 	/// This XML Writer makes the XML more simple by excluding the XSI attributes from the serializer
 | |
| 	/// </summary>
 | |
| 	public class NonXsiTextWriter : XmlTextWriter
 | |
| 	{
 | |
| 		public NonXsiTextWriter(TextWriter w) : base(w) { }
 | |
| 		public NonXsiTextWriter(Stream w, Encoding encoding)
 | |
| 			: base(w, encoding)
 | |
| 		{
 | |
| 			this.Formatting = Formatting.Indented;
 | |
| 		}
 | |
| 		public NonXsiTextWriter(string filename, Encoding encoding) : base(filename, encoding) { }
 | |
| 		bool _skip = false;
 | |
| 		public override void WriteStartAttribute(string prefix, string localName, string ns)
 | |
| 		{
 | |
| 			if ((prefix == "xmlns" && (localName == "xsd" || localName == "xsi")) || // Omits XSD and XSI declarations. 
 | |
| 				ns == XmlSchema.InstanceNamespace) // Omits all XSI attributes. 
 | |
| 			{
 | |
| 				_skip = true;
 | |
| 				return;
 | |
| 			}
 | |
| 			if (localName == "xlink_href")
 | |
| 				base.WriteStartAttribute(prefix, "xlink:href", ns);
 | |
| 			else
 | |
| 				base.WriteStartAttribute(prefix, localName, ns);
 | |
| 		}
 | |
| 		public override void WriteString(string text)
 | |
| 		{
 | |
| 			if (_skip) return;
 | |
| 			base.WriteString(text);
 | |
| 		}
 | |
| 		public override void WriteEndAttribute()
 | |
| 		{
 | |
| 			if (_skip)
 | |
| 			{ // Reset the flag, so we keep writing. 
 | |
| 				_skip = false;
 | |
| 				return;
 | |
| 			}
 | |
| 			base.WriteEndAttribute();
 | |
| 		}
 | |
| 	}
 | |
| 	/// <summary>
 | |
| 	/// Class to support moving a process window
 | |
| 	/// </summary>
 | |
| 	public class ProcessLocation
 | |
| 	{
 | |
| 		[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
 | |
| 		public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
 | |
| 		public const short SWP_NOMOVE = 0X2;
 | |
| 		public const short SWP_NOSIZE = 1;
 | |
| 		public const short SWP_NOZORDER = 0X4;
 | |
| 		public const int SWP_SHOWWINDOW = 0x0040;
 | |
| 
 | |
| 		private System.Diagnostics.Process _Process;
 | |
| 
 | |
| 		public System.Diagnostics.Process Process
 | |
| 		{
 | |
| 			get { return _Process; }
 | |
| 			set { _Process = value; }
 | |
| 		}
 | |
| 		private int _X;
 | |
| 		public int X
 | |
| 		{
 | |
| 			get { return _X; }
 | |
| 			set { _X = value; }
 | |
| 		}
 | |
| 		private int _Y;
 | |
| 		public int Y
 | |
| 		{
 | |
| 			get { return _Y; }
 | |
| 			set { _Y = value; }
 | |
| 		}
 | |
| 		public ProcessLocation(System.Diagnostics.Process process, int x, int y)
 | |
| 		{
 | |
| 			Process = process;
 | |
| 			X = x;
 | |
| 			Y = y;
 | |
| 		}
 | |
| 		private static Boolean FoxitSettingInfo = true;
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// MoveIt() moves the window containing the PDF viewer to the right so the two pdf viewer windows will not overlap.
 | |
| 		/// </summary>
 | |
| 		public void MoveIt()
 | |
| 		{
 | |
| 			try
 | |
| 			{
 | |
| 				SetWindowPos(Process.MainWindowHandle, 0, X, Y, 200, 400, SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);
 | |
| 			}
 | |
| 			catch // B2018-147 bring up message to inform user of the setting that will create separate windows of the pdf viewer
 | |
| 			{
 | |
| 				if (FoxitSettingInfo)
 | |
| 					MessageBox.Show("If you want to see the documents in separate windows,\nyou need to set Foxit to allow multiple instances. \nSelect File | preferences | Documents\n Check the Allow Multiple Instances", "Foxit Settings");
 | |
| 				FoxitSettingInfo = false;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	public class ProcessLocationQueue: Queue<ProcessLocation>
 | |
| 	{
 | |
| 		public void Add(System.Diagnostics.Process process, int x, int y)
 | |
| 		{
 | |
| 			Enqueue(new ProcessLocation(process,x,y));
 | |
| 		}
 | |
| 		public void ProcessNext()
 | |
| 		{
 | |
| 			ProcessLocation pl = Dequeue();
 | |
| 			pl.MoveIt();
 | |
| 		}
 | |
| 	}
 | |
| }
 |