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();
|
|
}
|
|
}
|
|
}
|