Forráskód Böngészése

Added code to convert images to PDFs on staging panel

Kenric Nugteren 1 éve
szülő
commit
7cf4ebcaae

+ 8 - 1
prs.desktop/Panels/Jobs/JobRequisitionItemGrid.cs

@@ -136,7 +136,14 @@ internal class JobRequisitionItemGrid : DynamicDataGrid<JobRequisitionItem>
         ref SortOrder<JobRequisitionItem>? sort,
         Action<CoreTable?, Exception?> action)
     {
-        criteria.Add(new Filter<JobRequisitionItem>(x => x.Requisition.ID).IsEqualTo(Requisition.ID));
+        if(Requisition.ID == Guid.Empty)
+        {
+            criteria.Add(new Filter<JobRequisitionItem>().None());
+        }
+        else
+        {
+            criteria.Add(new Filter<JobRequisitionItem>(x => x.Requisition.ID).IsEqualTo(Requisition.ID));
+        }
         base.Reload(criteria, columns, ref sort, action);
     }
 

+ 613 - 572
prs.desktop/Panels/Staging/Setouts/StagingSetoutGrid.cs

@@ -1,718 +1,759 @@
 using Comal.Classes;
-using Comal.Classes.Entities;
 using InABox.Clients;
 using InABox.Core;
 using InABox.DynamicGrid;
-using javax.print.attribute.standard;
-using Microsoft.Exchange.WebServices.Data;
 using Microsoft.Win32;
-using Syncfusion.Pdf.Parsing;
-using Syncfusion.UI.Xaml.Grid;
 using System;
 using System.Collections.Generic;
-using System.Drawing;
 using System.IO;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
-using System.Drawing.Imaging;
-using net.sf.mpxj.common;
 using System.ComponentModel;
 using InABox.WPF;
 using System.Windows.Media.Imaging;
 using InABox.Configuration;
-using NPOI.HSSF.Util;
 using System.Reactive.Linq;
 using InABox.Wpf;
 
-namespace PRSDesktop
+namespace PRSDesktop;
+
+public class StagingSetoutGridSettings : IUserConfigurationSettings
 {
-    
-    public class StagingSetoutGridSettings : IUserConfigurationSettings
-    {
-        [Obsolete]
-        private CoreFilterDefinition? _currentFilter;
+    [Obsolete]
+    private CoreFilterDefinition? _currentFilter;
 
-        [Obsolete]
-        public CoreFilterDefinition? CurrentFilter
+    [Obsolete]
+    public CoreFilterDefinition? CurrentFilter
+    {
+        get => _currentFilter;
+        set
         {
-            get => _currentFilter;
-            set
+            if (value is not null)
             {
-                if (value is not null)
-                {
-                    Filters = new DynamicGridSelectedFilterSettings(new List<CoreFilterDefinition> { value }, false, null);
-                }
+                Filters = new DynamicGridSelectedFilterSettings(new List<CoreFilterDefinition> { value }, false, null);
             }
         }
-
-        public DynamicGridSelectedFilterSettings Filters { get; set; } = new();
     }
 
+    public DynamicGridSelectedFilterSettings Filters { get; set; } = new();
+}
+
+
+public class StagingSetoutGrid : DynamicDataGrid<StagingSetout>
+{
     
-    public class StagingSetoutGrid : DynamicDataGrid<StagingSetout>
+    public class SetoutDocument
     {
-        
-        public class SetoutDocument
-        {
-            public Document Document { get; set; }
+        public Document Document { get; set; }
 
-            public StagingSetout Setout { get; set; }
+        public StagingSetout Setout { get; set; }
 
-            public SetoutDocument(Document document, StagingSetout setout)
-            {
-                Document = document;
-                Setout = setout;
-            }
+        public SetoutDocument(Document document, StagingSetout setout)
+        {
+            Document = document;
+            Setout = setout;
+        }
 
-            public void Deconstruct(out Document document, out StagingSetout setout)
-            {
-                document = Document;
-                setout = Setout;
-            }
+        public void Deconstruct(out Document document, out StagingSetout setout)
+        {
+            document = Document;
+            setout = Setout;
         }
+    }
+    
+    private StagingSetoutGridSettings _settings;
+    
+    public delegate void CustomiseSetoutsEvent(IReadOnlyList<SetoutDocument> setouts);
+    public event CustomiseSetoutsEvent? OnCustomiseSetouts;
+
+    public delegate void ParseComponentFile(string componentFileName, Guid setoutID);
+    public event ParseComponentFile? OnParseComponentFile;
+
+    public delegate void RefreshPacketsEvent();
+    public event RefreshPacketsEvent? OnRefreshPackets;
+
+    private readonly BitmapImage locked = PRSDesktop.Resources.locked.AsBitmapImage();
+    private readonly BitmapImage revision = PRSDesktop.Resources.revision.AsBitmapImage();
+    private readonly BitmapImage docs = PRSDesktop.Resources.design.AsBitmapImage();
+    private readonly BitmapImage packets = PRSDesktop.Resources.factory.AsBitmapImage();
+    private readonly BitmapImage tick = PRSDesktop.Resources.tick.AsBitmapImage();
+    private readonly BitmapImage warning = PRSDesktop.Resources.warning.AsBitmapImage();
+    private readonly BitmapImage rejected = PRSDesktop.Resources.disabled.AsBitmapImage();
+
+    private Button CopyPacketsButton;
+    private Button PastePacketsButton;
+    private StagingSetout? CopyPacketsSource;
+
+    public StagingPanellSettings PanelSettings { get; set; } = new StagingPanellSettings();
+
+    public StagingSetoutGrid()
+    {
+        HiddenColumns.Add(x => x.Setout.ID);
+        HiddenColumns.Add(x => x.JobLink.ID);
+        HiddenColumns.Add(x => x.Group.ID);
+        HiddenColumns.Add(x => x.Group.OptimizationDocument.ID);
+        HiddenColumns.Add(x => x.SavePath);
+        HiddenColumns.Add(x => x.OriginalPath);
+        HiddenColumns.Add(x => x.OriginalCRC);
+        HiddenColumns.Add(x => x.LockedBy.ID);
+        HiddenColumns.Add(x => x.LockedBy.Name);
+        HiddenColumns.Add(x => x.Packets);
+        HiddenColumns.Add(x => x.UnapprovedDocuments);
+        HiddenColumns.Add(x => x.UnprocessedPackets);
+        HiddenColumns.Add(x => x.Task.ID);
         
-        private StagingSetoutGridSettings _settings;
+        ActionColumns.Add(new DynamicTickColumn<StagingSetout,Guid>(x=>x.Setout.ID,revision,revision,null)
+        {
+            ToolTip = Revision_Tooltip,
+            Position = DynamicActionColumnPosition.Start
+        });
         
-        public delegate void CustomiseSetoutsEvent(IReadOnlyList<SetoutDocument> setouts);
-        public event CustomiseSetoutsEvent? OnCustomiseSetouts;
-
-        public delegate void ParseComponentFile(string componentFileName, Guid setoutID);
-        public event ParseComponentFile? OnParseComponentFile;
-
-        public delegate void RefreshPacketsEvent();
-        public event RefreshPacketsEvent? OnRefreshPackets;
-
-        private readonly BitmapImage locked = PRSDesktop.Resources.locked.AsBitmapImage();
-        private readonly BitmapImage revision = PRSDesktop.Resources.revision.AsBitmapImage();
-        private readonly BitmapImage docs = PRSDesktop.Resources.design.AsBitmapImage();
-        private readonly BitmapImage packets = PRSDesktop.Resources.factory.AsBitmapImage();
-        private readonly BitmapImage tick = PRSDesktop.Resources.tick.AsBitmapImage();
-        private readonly BitmapImage warning = PRSDesktop.Resources.warning.AsBitmapImage();
-        private readonly BitmapImage rejected = PRSDesktop.Resources.disabled.AsBitmapImage();
-
-        private Button CopyPacketsButton;
-        private Button PastePacketsButton;
-        private StagingSetout? CopyPacketsSource;
-
-        public StagingPanellSettings PanelSettings { get; set; } = new StagingPanellSettings();
-
-        public StagingSetoutGrid()
-        {
-            HiddenColumns.Add(x => x.Setout.ID);
-            HiddenColumns.Add(x => x.JobLink.ID);
-            HiddenColumns.Add(x => x.Group.ID);
-            HiddenColumns.Add(x => x.Group.OptimizationDocument.ID);
-            HiddenColumns.Add(x => x.SavePath);
-            HiddenColumns.Add(x => x.OriginalPath);
-            HiddenColumns.Add(x => x.OriginalCRC);
-            HiddenColumns.Add(x => x.LockedBy.ID);
-            HiddenColumns.Add(x => x.LockedBy.Name);
-            HiddenColumns.Add(x => x.Packets);
-            HiddenColumns.Add(x => x.UnapprovedDocuments);
-            HiddenColumns.Add(x => x.UnprocessedPackets);
-            HiddenColumns.Add(x => x.Task.ID);
-            
-            ActionColumns.Add(new DynamicTickColumn<StagingSetout,Guid>(x=>x.Setout.ID,revision,revision,null)
-            {
-                ToolTip = Revision_Tooltip,
-                Position = DynamicActionColumnPosition.Start
-            });
-            
-            ActionColumns.Add(new DynamicTickColumn<StagingSetout,Guid>(x=>x.LockedBy.ID,locked,locked,null)
-            {
-                ToolTip = Locked_Tooltip,
-                Position = DynamicActionColumnPosition.End
-            });
-            
-            ActionColumns.Add(new DynamicImageColumn(DesignImage)
-            {
-                ToolTip = Design_Tooltip,
-                Position = DynamicActionColumnPosition.End
-            });
+        ActionColumns.Add(new DynamicTickColumn<StagingSetout,Guid>(x=>x.LockedBy.ID,locked,locked,null)
+        {
+            ToolTip = Locked_Tooltip,
+            Position = DynamicActionColumnPosition.End
+        });
+        
+        ActionColumns.Add(new DynamicImageColumn(DesignImage)
+        {
+            ToolTip = Design_Tooltip,
+            Position = DynamicActionColumnPosition.End
+        });
 
-            ActionColumns.Add(new DynamicImageColumn(PacketsImage)
-            {
-                ToolTip = Packets_Tooltip,
-                Position = DynamicActionColumnPosition.End
-            });
+        ActionColumns.Add(new DynamicImageColumn(PacketsImage)
+        {
+            ToolTip = Packets_Tooltip,
+            Position = DynamicActionColumnPosition.End
+        });
 
-            ActionColumns.Add(new DynamicMenuColumn(Menu_Build));
-            
-            AddButton("Create Group", null, CreateGroup);
+        ActionColumns.Add(new DynamicMenuColumn(Menu_Build));
+        
+        AddButton("Create Group", null, CreateGroup);
 
-            CopyPacketsButton = AddButton("Copy Packets", PRSDesktop.Resources.copy.AsBitmapImage(), CopyPackets);
-            PastePacketsButton = AddButton("Paste Packets", InABox.Wpf.Resources.paste.AsBitmapImage(), PastePackets);
-            PastePacketsButton.Visibility = Visibility.Collapsed;
-        }
+        CopyPacketsButton = AddButton("Copy Packets", PRSDesktop.Resources.copy.AsBitmapImage(), CopyPackets);
+        PastePacketsButton = AddButton("Paste Packets", InABox.Wpf.Resources.paste.AsBitmapImage(), PastePackets);
+        PastePacketsButton.Visibility = Visibility.Collapsed;
+    }
 
-        protected override void SelectItems(CoreRow[]? rows)
-        {
-            base.SelectItems(rows);
+    protected override void SelectItems(CoreRow[]? rows)
+    {
+        base.SelectItems(rows);
 
-            if(CopyPacketsSource is null)
-            {
-                CopyPacketsButton.IsEnabled = rows?.Length == 1;
-                PastePacketsButton.IsEnabled = false;
-            }
-            else
-            {
-                CopyPacketsButton.IsEnabled = false;
-                PastePacketsButton.IsEnabled = rows is not null && rows.Length > 0
-                    && !rows.Any(x => x.Get<StagingSetout, Guid>(x => x.ID) == CopyPacketsSource.ID);
-            }
+        if(CopyPacketsSource is null)
+        {
+            CopyPacketsButton.IsEnabled = rows?.Length == 1;
+            PastePacketsButton.IsEnabled = false;
         }
+        else
+        {
+            CopyPacketsButton.IsEnabled = false;
+            PastePacketsButton.IsEnabled = rows is not null && rows.Length > 0
+                && !rows.Any(x => x.Get<StagingSetout, Guid>(x => x.ID) == CopyPacketsSource.ID);
+        }
+    }
 
-        private bool PastePackets(Button button, CoreRow[] rows)
+    private bool PastePackets(Button button, CoreRow[] rows)
+    {
+        if(CopyPacketsSource is null)
         {
-            if(CopyPacketsSource is null)
-            {
-                MessageBox.Show("Please first select a setout to copy from.");
-                return false;
-            }
-            else if (rows.Length == 0)
-            {
-                MessageBox.Show("Please select at least one setout to copy packets to.");
-                return false;
-            }
-            else if(rows.Any(x => x.Get<StagingSetout, Guid>(x => x.ID) == CopyPacketsSource.ID))
-            {
-                MessageBox.Show("Cannot copy packets from a setout to itself.");
-                return false;
-            }
+            MessageBox.Show("Please first select a setout to copy from.");
+            return false;
+        }
+        else if (rows.Length == 0)
+        {
+            MessageBox.Show("Please select at least one setout to copy packets to.");
+            return false;
+        }
+        else if(rows.Any(x => x.Get<StagingSetout, Guid>(x => x.ID) == CopyPacketsSource.ID))
+        {
+            MessageBox.Show("Cannot copy packets from a setout to itself.");
+            return false;
+        }
 
-            var packetFilter = new Filter<StagingManufacturingPacket>(x => x.StagingSetout.ID).IsEqualTo(CopyPacketsSource.ID);
-
-            var results = Client.QueryMultiple(
-                new KeyedQueryDef<StagingManufacturingPacket>(
-                    packetFilter,
-                    new Columns<StagingManufacturingPacket>(x => x.ID)
-                        .Add(x => x.Title)
-                        .Add(x => x.Job.ID)
-                        .Add(x => x.ITP.ID)
-                        .Add(x => x.Watermark)
-                        .Add(x => x.Location)
-                        .Add(x => x.Quantity)
-                        .Add(x => x.BarcodeQuantity)
-                        .Add(x => x.Group.ID)
-                        .Add(x => x.Group.Code)
-                        .Add(x => x.Template.ID)),
-                new KeyedQueryDef<StagingManufacturingPacketStage>(
-                    new Filter<StagingManufacturingPacketStage>(x => x.Packet.ID).InQuery(packetFilter, x => x.ID),
-                    new Columns<StagingManufacturingPacketStage>(x => x.Packet.ID)
-                        .Add(x => x.Section.ID)
-                        .Add(x => x.Time)
-                        .Add(x => x.SequenceType)
-                        .Add(x => x.Sequence)
-                        .Add(x => x.QualityChecks)),
-                new KeyedQueryDef<StagingManufacturingPacketTreatment>(
-                    new Filter<StagingManufacturingPacketTreatment>(x => x.Packet.ID).InQuery(packetFilter, x => x.ID),
-                    new Columns<StagingManufacturingPacketTreatment>(x => x.Packet.ID)
-                        .Add(x => x.Product.ID)
-                        .Add(x => x.Parameter)));
-
-            var stages = results.GetObjects<StagingManufacturingPacketStage>()
-                .GroupBy(x => x.Packet.ID)
-                .ToDictionary(x => x.Key, x => x.ToList());
-
-            var treatments = results.GetObjects<StagingManufacturingPacketTreatment>()
-                .GroupBy(x => x.Packet.ID)
-                .ToDictionary(x => x.Key, x => x.ToList());
-
-            var targets = rows.Select(x => x.ToObject<StagingSetout>()).ToList();
-
-            var currentPackets = Client.Query(
-                new Filter<StagingManufacturingPacket>(x => x.StagingSetout.ID).InList(targets.Select(x => x.ID).ToArray()),
-                new Columns<StagingManufacturingPacket>(x => x.StagingSetout.ID).Add(x => x.Serial))
-                .ToObjects<StagingManufacturingPacket>();
-
-            var newPackets = new List<(StagingManufacturingPacket originalPacket, StagingManufacturingPacket newPacket)>();
-            foreach(var target in targets)
+        var packetFilter = new Filter<StagingManufacturingPacket>(x => x.StagingSetout.ID).IsEqualTo(CopyPacketsSource.ID);
+
+        var results = Client.QueryMultiple(
+            new KeyedQueryDef<StagingManufacturingPacket>(
+                packetFilter,
+                new Columns<StagingManufacturingPacket>(x => x.ID)
+                    .Add(x => x.Title)
+                    .Add(x => x.Job.ID)
+                    .Add(x => x.ITP.ID)
+                    .Add(x => x.Watermark)
+                    .Add(x => x.Location)
+                    .Add(x => x.Quantity)
+                    .Add(x => x.BarcodeQuantity)
+                    .Add(x => x.Group.ID)
+                    .Add(x => x.Group.Code)
+                    .Add(x => x.Template.ID)),
+            new KeyedQueryDef<StagingManufacturingPacketStage>(
+                new Filter<StagingManufacturingPacketStage>(x => x.Packet.ID).InQuery(packetFilter, x => x.ID),
+                new Columns<StagingManufacturingPacketStage>(x => x.Packet.ID)
+                    .Add(x => x.Section.ID)
+                    .Add(x => x.Time)
+                    .Add(x => x.SequenceType)
+                    .Add(x => x.Sequence)
+                    .Add(x => x.QualityChecks)),
+            new KeyedQueryDef<StagingManufacturingPacketTreatment>(
+                new Filter<StagingManufacturingPacketTreatment>(x => x.Packet.ID).InQuery(packetFilter, x => x.ID),
+                new Columns<StagingManufacturingPacketTreatment>(x => x.Packet.ID)
+                    .Add(x => x.Product.ID)
+                    .Add(x => x.Parameter)));
+
+        var stages = results.GetObjects<StagingManufacturingPacketStage>()
+            .GroupBy(x => x.Packet.ID)
+            .ToDictionary(x => x.Key, x => x.ToList());
+
+        var treatments = results.GetObjects<StagingManufacturingPacketTreatment>()
+            .GroupBy(x => x.Packet.ID)
+            .ToDictionary(x => x.Key, x => x.ToList());
+
+        var targets = rows.Select(x => x.ToObject<StagingSetout>()).ToList();
+
+        var currentPackets = Client.Query(
+            new Filter<StagingManufacturingPacket>(x => x.StagingSetout.ID).InList(targets.Select(x => x.ID).ToArray()),
+            new Columns<StagingManufacturingPacket>(x => x.StagingSetout.ID).Add(x => x.Serial))
+            .ToObjects<StagingManufacturingPacket>();
+
+        var newPackets = new List<(StagingManufacturingPacket originalPacket, StagingManufacturingPacket newPacket)>();
+        foreach(var target in targets)
+        {
+            foreach (var originalPacket in results.GetObjects<StagingManufacturingPacket>())
             {
-                foreach (var originalPacket in results.GetObjects<StagingManufacturingPacket>())
+                var newPacket = new StagingManufacturingPacket
                 {
-                    var newPacket = new StagingManufacturingPacket
-                    {
-                        Title = originalPacket.Title,
-                        Watermark = originalPacket.Watermark,
-                        Location = originalPacket.Location,
-                        Quantity = originalPacket.Quantity,
-                        BarcodeQuantity = originalPacket.BarcodeQuantity
-                    };
-                    newPacket.Group.ID = originalPacket.Group.ID;
-                    newPacket.Template.ID = originalPacket.Template.ID;
-                    if(originalPacket.Job.ID == target.JobLink.ID)
-                    {
-                        newPacket.Job.ID = originalPacket.Job.ID;
-                        newPacket.ITP.ID = originalPacket.ITP.ID;
-                    }
-                    newPacket.Serial = StagingManufacturingPacketList.GenerateSerialNumber(target, originalPacket.Group.Code,
-                        Enumerable.Concat(newPackets.Select(x => x.newPacket), currentPackets.Where(x => x.StagingSetout.ID == target.ID)));
-                    newPacket.StagingSetout.ID = target.ID;
-                    newPackets.Add((originalPacket, newPacket));
+                    Title = originalPacket.Title,
+                    Watermark = originalPacket.Watermark,
+                    Location = originalPacket.Location,
+                    Quantity = originalPacket.Quantity,
+                    BarcodeQuantity = originalPacket.BarcodeQuantity
+                };
+                newPacket.Group.ID = originalPacket.Group.ID;
+                newPacket.Template.ID = originalPacket.Template.ID;
+                if(originalPacket.Job.ID == target.JobLink.ID)
+                {
+                    newPacket.Job.ID = originalPacket.Job.ID;
+                    newPacket.ITP.ID = originalPacket.ITP.ID;
                 }
+                newPacket.Serial = StagingManufacturingPacketList.GenerateSerialNumber(target, originalPacket.Group.Code,
+                    Enumerable.Concat(newPackets.Select(x => x.newPacket), currentPackets.Where(x => x.StagingSetout.ID == target.ID)));
+                newPacket.StagingSetout.ID = target.ID;
+                newPackets.Add((originalPacket, newPacket));
             }
-            Client.Save(newPackets.Select(x => x.newPacket), $"Copied from setout '{CopyPacketsSource.Number}'");
+        }
+        Client.Save(newPackets.Select(x => x.newPacket), $"Copied from setout '{CopyPacketsSource.Number}'");
 
-            var newStages = new List<StagingManufacturingPacketStage>();
-            var newTreatments = new List<StagingManufacturingPacketTreatment>();
+        var newStages = new List<StagingManufacturingPacketStage>();
+        var newTreatments = new List<StagingManufacturingPacketTreatment>();
 
-            foreach(var (originalPacket, newPacket) in newPackets)
+        foreach(var (originalPacket, newPacket) in newPackets)
+        {
+            if(stages.TryGetValue(originalPacket.ID, out var originalStages))
             {
-                if(stages.TryGetValue(originalPacket.ID, out var originalStages))
+                foreach(var originalStage in originalStages)
                 {
-                    foreach(var originalStage in originalStages)
-                    {
-                        var newStage = new StagingManufacturingPacketStage();
-                        newStage.Packet.ID = newPacket.ID;
-                        newStage.Section.ID = originalStage.Section.ID;
-                        newStage.Time = originalStage.Time;
-                        newStage.SequenceType = originalStage.SequenceType;
-                        newStage.Sequence = originalStage.Sequence;
-                        newStage.QualityChecks = originalStage.QualityChecks;
-                        newStages.Add(newStage);
-                    }
+                    var newStage = new StagingManufacturingPacketStage();
+                    newStage.Packet.ID = newPacket.ID;
+                    newStage.Section.ID = originalStage.Section.ID;
+                    newStage.Time = originalStage.Time;
+                    newStage.SequenceType = originalStage.SequenceType;
+                    newStage.Sequence = originalStage.Sequence;
+                    newStage.QualityChecks = originalStage.QualityChecks;
+                    newStages.Add(newStage);
                 }
-                if (treatments.TryGetValue(originalPacket.ID, out var originalTreatments))
+            }
+            if (treatments.TryGetValue(originalPacket.ID, out var originalTreatments))
+            {
+                foreach (var originalTreatment in originalTreatments)
                 {
-                    foreach (var originalTreatment in originalTreatments)
-                    {
-                        var newTreatment = new StagingManufacturingPacketTreatment();
-                        newTreatment.Packet.ID = newPacket.ID;
-                        newTreatment.Product.ID = originalTreatment.Product.ID;
-                        newTreatment.Parameter = originalTreatment.Parameter;
-                        newTreatments.Add(newTreatment);
-                    }
+                    var newTreatment = new StagingManufacturingPacketTreatment();
+                    newTreatment.Packet.ID = newPacket.ID;
+                    newTreatment.Product.ID = originalTreatment.Product.ID;
+                    newTreatment.Parameter = originalTreatment.Parameter;
+                    newTreatments.Add(newTreatment);
                 }
             }
+        }
 
-            Client.Save(newStages, $"Copied from setout '{CopyPacketsSource.Number}'");
-            Client.Save(newTreatments, $"Copied from setout '{CopyPacketsSource.Number}'");
+        Client.Save(newStages, $"Copied from setout '{CopyPacketsSource.Number}'");
+        Client.Save(newTreatments, $"Copied from setout '{CopyPacketsSource.Number}'");
 
-            CopyPacketsSource = null;
-            CopyPacketsButton.Visibility = Visibility.Visible;
-            PastePacketsButton.Visibility = Visibility.Collapsed;
+        CopyPacketsSource = null;
+        CopyPacketsButton.Visibility = Visibility.Visible;
+        PastePacketsButton.Visibility = Visibility.Collapsed;
 
-            OnRefreshPackets?.Invoke();
+        OnRefreshPackets?.Invoke();
+        return false;
+    }
+
+    private bool CopyPackets(Button button, CoreRow[] rows)
+    {
+        if (rows.Length == 0)
+        {
+            MessageBox.Show("Please select a setout to copy packets from.");
             return false;
         }
-
-        private bool CopyPackets(Button button, CoreRow[] rows)
+        else if (rows.Length != 1)
         {
-            if (rows.Length == 0)
-            {
-                MessageBox.Show("Please select a setout to copy packets from.");
-                return false;
-            }
-            else if (rows.Length != 1)
-            {
-                MessageBox.Show("Cannot copy packets from more than one setout.");
-                return false;
-            }
-
-            CopyPacketsSource = rows.First().ToObject<StagingSetout>();
-            CopyPacketsButton.Visibility = Visibility.Collapsed;
-            PastePacketsButton.Visibility = Visibility.Visible;
-
+            MessageBox.Show("Cannot copy packets from more than one setout.");
             return false;
         }
 
-        private void Menu_Build(DynamicMenuColumn column, CoreRow? row)
+        CopyPacketsSource = rows.First().ToObject<StagingSetout>();
+        CopyPacketsButton.Visibility = Visibility.Collapsed;
+        PastePacketsButton.Visibility = Visibility.Visible;
+
+        return false;
+    }
+
+    private void Menu_Build(DynamicMenuColumn column, CoreRow? row)
+    {
+        if(row is null)
         {
-            if(row is null)
-            {
-                return;
-            }
-            column.AddItem("Import Components", PRSDesktop.Resources.doc_xls, ImportComponents);
+            return;
         }
+        column.AddItem("Import Components", PRSDesktop.Resources.doc_xls, ImportComponents);
+    }
 
-        private void ImportComponents(CoreRow? row)
+    private void ImportComponents(CoreRow? row)
+    {
+        if(row is null)
         {
-            if(row is null)
-            {
-                return;
-            }
-            var dlg = new OpenFileDialog
-            {
-                Multiselect = true,
-                Title = "Add Component Files",
-                Filter = "Component Files (*.xls;*.xlsx;*.csv;*.txt)|*.xls;*.xlsx;*.csv;*.txt|All Files (*.*)|*.*"
-            };
-            if (dlg.ShowDialog() == true)
-            {
-                AddComponentFiles(dlg.FileNames, row.Get<StagingSetout, Guid>(x => x.ID));
-            }
+            return;
         }
-
-        private FrameworkElement? Revision_Tooltip(DynamicActionColumn column, CoreRow? row)
+        var dlg = new OpenFileDialog
         {
-            if(row is null)
-                return column.TextToolTip("Linked Design Status?");
-            
-            if (row.Get<StagingSetout, Guid>(x => x.Setout.ID) != Guid.Empty)
-                return column.TextToolTip($"This is a revision of an existing design");
-            
-            return null;
-        }        
-        
-        private FrameworkElement? Locked_Tooltip(DynamicActionColumn column, CoreRow? row)
+            Multiselect = true,
+            Title = "Add Component Files",
+            Filter = "Component Files (*.xls;*.xlsx;*.csv;*.txt)|*.xls;*.xlsx;*.csv;*.txt|All Files (*.*)|*.*"
+        };
+        if (dlg.ShowDialog() == true)
         {
-            if(row is null)
-                return column.TextToolTip("Is this Design Locked?");
-            
-            var islocked = row.Get<StagingSetout, Guid>(x => x.LockedBy.ID);
-            if (islocked != Guid.Empty)
-                return column.TextToolTip($"This design is locked by {row.Get<StagingSetout, String>(x => x.LockedBy.Name)}");
-            
-            return null;
+            AddComponentFiles(dlg.FileNames, row.Get<StagingSetout, Guid>(x => x.ID));
         }
+    }
+
+    private FrameworkElement? Revision_Tooltip(DynamicActionColumn column, CoreRow? row)
+    {
+        if(row is null)
+            return column.TextToolTip("Linked Design Status?");
         
-        private BitmapImage? DesignImage(CoreRow? arg)
-        {
-            if (arg is null)
-                return docs;
-            if (arg.Get<StagingSetout, Guid>(x => x.Task.ID) != Guid.Empty)
-                return rejected;
-            if(arg.Get<StagingSetout, int>(x => x.UnapprovedDocuments) == 0)
-                return tick;
-            return warning;
-        }
+        if (row.Get<StagingSetout, Guid>(x => x.Setout.ID) != Guid.Empty)
+            return column.TextToolTip($"This is a revision of an existing design");
         
-        private FrameworkElement? Design_Tooltip(DynamicActionColumn column, CoreRow? row)
-        {
-            if(row is null)
-                return column.TextToolTip("Is this Design Approved?");
-            
-            var task = row.Get<StagingSetout, Guid>(x => x.Task.ID);
-            if (task != Guid.Empty)
-                return column.TextToolTip("This design has been rejected.");
-            
-            var unapproved = row.Get<StagingSetout, int>(x => x.UnapprovedDocuments);
-            if (unapproved == 0)
-                return column.TextToolTip("This design has been approved."); 
-            
-            return column.TextToolTip($"This design requires checking and approval.");
-        }
+        return null;
+    }        
+    
+    private FrameworkElement? Locked_Tooltip(DynamicActionColumn column, CoreRow? row)
+    {
+        if(row is null)
+            return column.TextToolTip("Is this Design Locked?");
         
-        private BitmapImage? PacketsImage(CoreRow? arg)
-        {
-            if (arg is null)
-                return packets;
-            if ((arg.Get<StagingSetout, int>(x => x.Packets) > 0) && (arg.Get<StagingSetout, int>(x => x.UnprocessedPackets) == 0))
-                return tick;
-            return warning;
-        }
-
-        private FrameworkElement? Packets_Tooltip(DynamicActionColumn column, CoreRow? row)
-        {
-            if (row is null)
-                return column.TextToolTip("Manufacturing Packets Status");
-            
-            var packetcount = row.Get<StagingSetout, int>(x => x.Packets);
-            if (packetcount == 0)
-                return column.TextToolTip("This design has no packets defined!");
-            
-            var unprocessed = row.Get<StagingSetout, int>(x => x.UnprocessedPackets);
-            if (unprocessed > 0)
-                return column.TextToolTip($"This design has {unprocessed} unprocessed packet{(unprocessed > 1 ? "s" : "")}.");
+        var islocked = row.Get<StagingSetout, Guid>(x => x.LockedBy.ID);
+        if (islocked != Guid.Empty)
+            return column.TextToolTip($"This design is locked by {row.Get<StagingSetout, String>(x => x.LockedBy.Name)}");
+        
+        return null;
+    }
+    
+    private BitmapImage? DesignImage(CoreRow? arg)
+    {
+        if (arg is null)
+            return docs;
+        if (arg.Get<StagingSetout, Guid>(x => x.Task.ID) != Guid.Empty)
+            return rejected;
+        if(arg.Get<StagingSetout, int>(x => x.UnapprovedDocuments) == 0)
+            return tick;
+        return warning;
+    }
+    
+    private FrameworkElement? Design_Tooltip(DynamicActionColumn column, CoreRow? row)
+    {
+        if(row is null)
+            return column.TextToolTip("Is this Design Approved?");
+        
+        var task = row.Get<StagingSetout, Guid>(x => x.Task.ID);
+        if (task != Guid.Empty)
+            return column.TextToolTip("This design has been rejected.");
+        
+        var unapproved = row.Get<StagingSetout, int>(x => x.UnapprovedDocuments);
+        if (unapproved == 0)
+            return column.TextToolTip("This design has been approved."); 
+        
+        return column.TextToolTip($"This design requires checking and approval.");
+    }
+    
+    private BitmapImage? PacketsImage(CoreRow? arg)
+    {
+        if (arg is null)
+            return packets;
+        if ((arg.Get<StagingSetout, int>(x => x.Packets) > 0) && (arg.Get<StagingSetout, int>(x => x.UnprocessedPackets) == 0))
+            return tick;
+        return warning;
+    }
 
-            return column.TextToolTip($"All packets for this design have been processed.");
-        }
+    private FrameworkElement? Packets_Tooltip(DynamicActionColumn column, CoreRow? row)
+    {
+        if (row is null)
+            return column.TextToolTip("Manufacturing Packets Status");
         
-        protected override void Init()
-        {
-            base.Init();
-            _settings = new UserConfiguration<StagingSetoutGridSettings>().Load();
-            FilterComponent.SetSettings(_settings.Filters, false);
-            FilterComponent.OnFiltersSelected += FilterComponent_OnFilterSelected;
-        }
+        var packetcount = row.Get<StagingSetout, int>(x => x.Packets);
+        if (packetcount == 0)
+            return column.TextToolTip("This design has no packets defined!");
+        
+        var unprocessed = row.Get<StagingSetout, int>(x => x.UnprocessedPackets);
+        if (unprocessed > 0)
+            return column.TextToolTip($"This design has {unprocessed} unprocessed packet{(unprocessed > 1 ? "s" : "")}.");
 
-        protected override void DoReconfigure(FluentList<DynamicGridOption> options)
-        {
-            base.DoReconfigure(options);
+        return column.TextToolTip($"All packets for this design have been processed.");
+    }
+    
+    protected override void Init()
+    {
+        base.Init();
+        _settings = new UserConfiguration<StagingSetoutGridSettings>().Load();
+        FilterComponent.SetSettings(_settings.Filters, false);
+        FilterComponent.OnFiltersSelected += FilterComponent_OnFilterSelected;
+    }
 
-            options.BeginUpdate();
-            options.Add(DynamicGridOption.FilterRows);
-            options.Add(DynamicGridOption.SelectColumns);
-            options.Add(DynamicGridOption.RecordCount);
-            options.Remove(DynamicGridOption.ImportData);
+    protected override void DoReconfigure(FluentList<DynamicGridOption> options)
+    {
+        base.DoReconfigure(options);
 
-            if (Security.IsAllowed<CanApproveSetouts>())
-                options.Add(DynamicGridOption.DeleteRows);
-            options.EndUpdate();
-        }
+        options.BeginUpdate();
+        options.Add(DynamicGridOption.FilterRows);
+        options.Add(DynamicGridOption.SelectColumns);
+        options.Add(DynamicGridOption.RecordCount);
+        options.Remove(DynamicGridOption.ImportData);
 
-        private bool CreateGroup(Button arg1, CoreRow[] rows)
-        {
-            if (!rows.Any())
-            {
-                MessageBox.Show("Please select at least one row to add to group");
-                return false;
-            }
+        if (Security.IsAllowed<CanApproveSetouts>())
+            options.Add(DynamicGridOption.DeleteRows);
+        options.EndUpdate();
+    }
 
-            var list = rows.Select(x => x.ToObject<StagingSetout>()).ToList();
+    private bool CreateGroup(Button arg1, CoreRow[] rows)
+    {
+        if (!rows.Any())
+        {
+            MessageWindow.ShowMessage("Please select at least one row to add to group", "No rows selected.");
+            return false;
+        }
 
-            string message = "";
-            foreach (var staging in list)
-                message = message + staging.Number + Environment.NewLine;
+        var list = rows.Select(x => x.ToObject<StagingSetout>()).ToList();
 
-            if (MessageBox.Show("Create group for the following items?" + Environment.NewLine + message, "Proceed?", MessageBoxButton.OKCancel) != MessageBoxResult.OK)
-                return false;
+        string message = "";
+        foreach (var staging in list)
+            message = message + staging.Number + Environment.NewLine;
 
-            var group = new SetoutGroup();
-            var page = new DynamicDataGrid<SetoutGroup>();
-            page.OnAfterSave += (editor, items) =>
-            {
-                foreach (var staging in list)
-                {
-                    staging.Group.ID = group.ID;
-                }
-                new Client<StagingSetout>().Save(list, "Updated group");
-                Refresh(false, true);
-            };
-            return page.EditItems(new[] { group });
-        }
+        if (!MessageWindow.ShowOKCancel("Create group for the following items?" + Environment.NewLine + message, "Proceed?"))
+            return false;
 
-        protected override void DoAdd(bool OpenEditorOnDirectEdit = false)
+        var group = new SetoutGroup();
+        var page = new DynamicDataGrid<SetoutGroup>();
+        page.OnAfterSave += (editor, items) =>
         {
-            var dlg = new OpenFileDialog
-            {
-                Multiselect = true,
-                Title = "Add Staging Files",
-                Filter = "PDF and Component Files (*.pdf;*.xls;*.xlsx;*.csv;*.txt)|*.pdf;*.xls;*.xlsx;*.csv;*.txt|PDF Files (*.pdf)|*.pdf|Component Files (*.xls;*.xlsx;*.csv;*.txt)|*.xls;*.xlsx;*.csv;*.txt|All Files (*.*)|*.*"
-            };
-            if (dlg.ShowDialog() == true)
+            foreach (var staging in list)
             {
-                var (pdfs, components) = dlg.FileNames.PartitionToList(x => Path.GetExtension(x).Equals(".pdf"));
-                AddPDFFiles(pdfs);
-                AddComponentFiles(components, Guid.Empty);
+                staging.Group.ID = group.ID;
             }
-        }
+            new Client<StagingSetout>().Save(list, "Updated group");
+            Refresh(false, true);
+        };
+        return page.EditItems(new[] { group });
+    }
 
-        public void AddPDFFiles(IEnumerable<string> fileNames)
+    protected override void DoAdd(bool OpenEditorOnDirectEdit = false)
+    {
+        var dlg = new OpenFileDialog
         {
-            var stagingdocs = new List<StagingSetoutDocument>();
-
-            var cancel = new CancelEventArgs();
-
-            // Convert MB to B
-            var maximum = PanelSettings.MaximumDocumentSize * 1000 * 1000;
-            if(maximum > 0)
+            Multiselect = true,
+            Title = "Add Staging Files",
+            Filter = "PDF and Component Files (*.pdf;*.xls;*.xlsx;*.csv;*.txt)|*.pdf;*.xls;*.xlsx;*.csv;*.txt|" +
+            "PDF Files (*.pdf)|*.pdf|" +
+            "Component Files (*.xls;*.xlsx;*.csv;*.txt)|*.xls;*.xlsx;*.csv;*.txt|" +
+            "Image Files (*.bmp;*.png;*.jpg;*.jpeg)|*.bmp;*.png;*.jpg;*.jpeg|" +
+            "All Files (*.*)|*.*"
+        };
+        if (dlg.ShowDialog() == true)
+        {
+            var pdfs = new List<string>();
+            var images = new List<string>();
+            var components = new List<string>();
+            foreach(var filename in dlg.FileNames)
             {
-                var tooLarge = fileNames.Where(x =>
+                var ext = Path.GetExtension(filename).ToLower();
+                if(ext == ".pdf")
                 {
-                    var fileSize = new FileInfo(x).Length;
-                    return fileSize > maximum;
-                }).ToList();
-                if(tooLarge.Count > 0)
+                    pdfs.Add(filename);
+                }
+                else if(ext == ".bmp" || ext == ".png" || ext == ".jpg" || ext == ".jpeg")
                 {
-                    if(!MessageWindow.ShowYesNo($"The following files are larger than {PanelSettings.MaximumDocumentSize} MB. Are you sure you wish to continue?\n\n{string.Join('\n', tooLarge)}", "Large files"))
-                    {
-                        return;
-                    }
+                    images.Add(filename);
+                }
+                else
+                {
+                    components.Add(filename);
                 }
             }
 
-            var newDocuments = fileNames.Select(x =>
+            AddPDFFiles(pdfs, doRefresh: false);
+            AddImageFiles(images, doRefresh: false);
+            AddComponentFiles(components, Guid.Empty);
+
+            Refresh(false, true);
+        }
+    }
+
+    private void AddDocuments(IEnumerable<Tuple<string, Document>> documents, bool doRefresh)
+    {
+        var newDocuments = documents.Select(x =>
+        {
+            var (filename, file) = x;
+            return new SetoutDocument(file, new StagingSetout
             {
-                var file = ReadFile(x);
-                return new SetoutDocument(file, new StagingSetout
-                {
-                    Number = Path.GetFileNameWithoutExtension(file.FileName),
-                    OriginalPath = x,
-                    OriginalCRC = file.CRC
-                });
-            }).ToList();
+                Number = Path.GetFileNameWithoutExtension(file.FileName),
+                OriginalPath = filename,
+                OriginalCRC = file.CRC
+            });
+        }).ToList();
+
+        var checkNumbers = newDocuments.Select(x => x.Setout.Number).ToArray();
+        var clashSetouts = new Client<StagingSetout>()
+            .Query(
+                new Filter<StagingSetout>(x => x.Number).InList(checkNumbers),
+                new Columns<StagingSetout>(x => x.ID).Add(x => x.Number))
+            .ToObjects<StagingSetout>().ToList();
 
-            var checkNumbers = newDocuments.Select(x => x.Setout.Number).ToArray();
-            var clashSetouts = new Client<StagingSetout>()
+        var setoutsToDelete = new List<StagingSetout>();
+        if (clashSetouts.Any())
+        {
+            var setoutDocuments = new Client<StagingSetoutDocument>()
                 .Query(
-                    new Filter<StagingSetout>(x => x.Number).InList(checkNumbers),
-                    new Columns<StagingSetout>(x => x.ID).Add(x => x.Number))
-                .ToObjects<StagingSetout>().ToList();
+                    new Filter<StagingSetoutDocument>(x => x.EntityLink.ID).InList(clashSetouts.Select(x => x.ID).ToArray()),
+                    new Columns<StagingSetoutDocument>(x => x.ID).Add(x => x.EntityLink.ID).Add(x => x.DocumentLink.CRC));
 
-            var setoutsToDelete = new List<StagingSetout>();
-            if (clashSetouts.Any())
+            foreach (var doc in setoutDocuments.ToObjects<StagingSetoutDocument>())
             {
-                var setoutDocuments = new Client<StagingSetoutDocument>()
-                    .Query(
-                        new Filter<StagingSetoutDocument>(x => x.EntityLink.ID).InList(clashSetouts.Select(x => x.ID).ToArray()),
-                        new Columns<StagingSetoutDocument>(x => x.ID).Add(x => x.EntityLink.ID).Add(x => x.DocumentLink.CRC));
+                // This setout must exist based on the filter.
+                var setout = clashSetouts.First(x => x.ID == doc.EntityLink.ID);
 
-                foreach(var doc in setoutDocuments.ToObjects<StagingSetoutDocument>())
+                // This document must exist also based on the filter, however it may have been removed.
+                var newDoc = newDocuments.FirstOrDefault(x => x.Setout.Number == setout.Number);
+                if (newDoc is not null)
                 {
-                    // This setout must exist based on the filter.
-                    var setout = clashSetouts.First(x => x.ID == doc.EntityLink.ID);
-
-                    // This document must exist also based on the filter, however it may have been removed.
-                    var newDoc = newDocuments.FirstOrDefault(x => x.Setout.Number == setout.Number);
-                    if(newDoc is not null)
+                    if (doc.DocumentLink.CRC != newDoc.Document.CRC)
                     {
-                        if (doc.DocumentLink.CRC != newDoc.Document.CRC)
+                        // We only care if the CRC is different, because this means the same file is being re-uploaded.
+                        var result = MessageBox.Show($"A different setout with the number '{setout.Number}' already exists. Do you wish to replace the existing setout with the new one?", "Replace Existing", MessageBoxButton.YesNoCancel);
+                        if (result == MessageBoxResult.Yes)
                         {
-                            // We only care if the CRC is different, because this means the same file is being re-uploaded.
-                            var result = MessageBox.Show($"A different setout with the number '{setout.Number}' already exists. Do you wish to replace the existing setout with the new one?", "Replace Existing", MessageBoxButton.YesNoCancel);
-                            if (result == MessageBoxResult.Yes)
-                            {
-                                setoutsToDelete.Add(setout);
-                            }
-                            else if (result == MessageBoxResult.No)
-                            {
-                                newDocuments.Remove(newDoc);
-                            }
-                            else if (result == MessageBoxResult.Cancel)
-                            {
-                                return;
-                            }
+                            setoutsToDelete.Add(setout);
                         }
-                        else
+                        else if (result == MessageBoxResult.No)
                         {
-                            // Already exists, ignore this document.
                             newDocuments.Remove(newDoc);
                         }
+                        else if (result == MessageBoxResult.Cancel)
+                        {
+                            return;
+                        }
+                    }
+                    else
+                    {
+                        // Already exists, ignore this document.
+                        newDocuments.Remove(newDoc);
                     }
                 }
             }
+        }
 
-            new Client<Document>().Save(newDocuments.Select(x => x.Document), "Created from sync setout function");
+        Client.Save(newDocuments.Select(x => x.Document), "Created from sync setout function");
 
-            OnCustomiseSetouts?.Invoke(newDocuments);
-            new Client<StagingSetout>().Save(newDocuments.Select(x => x.Setout), "Created from sync setout function");
+        OnCustomiseSetouts?.Invoke(newDocuments);
+        Client.Save(newDocuments.Select(x => x.Setout), "Created from sync setout function");
 
-            foreach(var (doc, setout) in newDocuments)
-            {
-                var stagingsetoutdoc = new StagingSetoutDocument();
-                stagingsetoutdoc.EntityLink.ID = setout.ID;
-                stagingsetoutdoc.DocumentLink.ID = doc.ID;
-                stagingdocs.Add(stagingsetoutdoc);
-            }
-            new Client<StagingSetoutDocument>().Save(stagingdocs, "Created from sync setout function");
+        var stagingdocs = newDocuments.Select(x =>
+        {
+            var stagingsetoutdoc = new StagingSetoutDocument();
+            stagingsetoutdoc.EntityLink.ID = x.Setout.ID;
+            stagingsetoutdoc.DocumentLink.ID = x.Document.ID;
+            return stagingsetoutdoc;
+        });
 
-            if (setoutsToDelete.Any())
-            {
-                new Client<StagingSetout>().Delete(setoutsToDelete, "Replaced by new setout");
-            }
+        Client.Save(stagingdocs, "Created from sync setout function");
+
+        if (setoutsToDelete.Any())
+        {
+            Client.Delete(setoutsToDelete, "Replaced by new setout");
+        }
 
+        if (doRefresh)
+        {
             Refresh(false, true);
         }
+    }
 
-        public void AddComponentFiles(IEnumerable<string> fileNames, Guid setoutID)
+    public void AddPDFFiles(IEnumerable<string> fileNames, bool doRefresh = true)
+    {
+        var cancel = new CancelEventArgs();
+
+        // Convert MB to B
+        var maximum = PanelSettings.MaximumDocumentSize * 1000 * 1000;
+        if(maximum > 0)
         {
-            foreach(var file in fileNames)
+            var tooLarge = fileNames.Where(x =>
             {
-                OnParseComponentFile?.Invoke(file, setoutID);
+                var fileSize = new FileInfo(x).Length;
+                return fileSize > maximum;
+            }).ToList();
+            if(tooLarge.Count > 0)
+            {
+                if(!MessageWindow.ShowYesNo($"The following files are larger than {PanelSettings.MaximumDocumentSize} MB. Are you sure you wish to continue?\n\n{string.Join('\n', tooLarge)}", "Large files"))
+                {
+                    return;
+                }
             }
         }
 
-        /// <summary>
-        /// Requires the fully qualified file name
-        /// </summary>
-        /// <param name="file"></param>
-        /// <returns></returns>
-        private static Document ReadFile(string file)
+        AddDocuments(fileNames.Select(x =>
         {
-            var doc = new Document
-            {
-                FileName = Path.GetFileName(file),
-                Data = GetData(file)
-            };
-            doc.CRC = CoreUtils.CalculateCRC(doc.Data);
-            return doc;
-        }
+            return new Tuple<string, Document>(x, Document.FromFile(x));
+        }), doRefresh: doRefresh);
+    }
 
-        private static byte[] GetData(string file)
+    public void AddImageFiles(IEnumerable<string> fileNames, bool doRefresh = true)
+    {
+        AddDocuments(fileNames.Select(x =>
         {
-            Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
-            byte[] pdfData = new byte[stream.Length];
-            stream.Read(pdfData, 0, Convert.ToInt32(pdfData.Length));
-            stream.Dispose();
-            return pdfData;
+            var pdf = DataEntryReGroupWindow.RenderToPDF(x);
+            var data = pdf.SaveToBytes();
+            return new Tuple<string, Document>(
+                x,
+                new Document
+                {
+                    Data = data,
+                    FileName = Path.GetFileName(x),
+                    CRC = CoreUtils.CalculateCRC(data),
+                    TimeStamp = new FileInfo(x).LastWriteTime
+                });
+        }), doRefresh: doRefresh);
+    }
+
+    public void AddComponentFiles(IEnumerable<string> fileNames, Guid setoutID)
+    {
+        foreach(var file in fileNames)
+        {
+            OnParseComponentFile?.Invoke(file, setoutID);
         }
+    }
 
-        public static void ReloadFile(StagingSetout stagingSetout)
+    /// <summary>
+    /// Requires the fully qualified file name
+    /// </summary>
+    /// <param name="file"></param>
+    /// <returns></returns>
+    private static Document ReadFile(string file)
+    {
+        var doc = new Document
         {
-            if (string.IsNullOrWhiteSpace(stagingSetout.SavePath))
-                return;
+            FileName = Path.GetFileName(file),
+            Data = GetData(file)
+        };
+        doc.CRC = CoreUtils.CalculateCRC(doc.Data);
+        return doc;
+    }
 
-            var setoutDocument = new Client<StagingSetoutDocument>()
-                .Query(
-                    new Filter<StagingSetoutDocument>(x => x.EntityLink.ID).IsEqualTo(stagingSetout.ID),
-                    new Columns<StagingSetoutDocument>(x => x.DocumentLink.ID))
-                .ToObjects<StagingSetoutDocument>().FirstOrDefault();
-            if(setoutDocument is null)
-            {
-                MessageBox.Show("Could not find the document in the database.");
-                return;
-            }
+    private static byte[] GetData(string file)
+    {
+        Stream stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
+        byte[] pdfData = new byte[stream.Length];
+        stream.Read(pdfData, 0, Convert.ToInt32(pdfData.Length));
+        stream.Dispose();
+        return pdfData;
+    }
 
-            var doc = new Client<Document>()
-                .Query(
-                    new Filter<Document>(x => x.ID).IsEqualTo(setoutDocument.DocumentLink.ID),
-                    new Columns<Document>(x => x.ID))
-                .ToObjects<Document>().FirstOrDefault();
-            
-            try
+    public static void ReloadFile(StagingSetout stagingSetout)
+    {
+        if (string.IsNullOrWhiteSpace(stagingSetout.SavePath))
+            return;
+
+        var setoutDocument = new Client<StagingSetoutDocument>()
+            .Query(
+                new Filter<StagingSetoutDocument>(x => x.EntityLink.ID).IsEqualTo(stagingSetout.ID),
+                new Columns<StagingSetoutDocument>(x => x.DocumentLink.ID))
+            .ToObjects<StagingSetoutDocument>().FirstOrDefault();
+        if(setoutDocument is null)
+        {
+            MessageBox.Show("Could not find the document in the database.");
+            return;
+        }
+
+        var doc = new Client<Document>()
+            .Query(
+                new Filter<Document>(x => x.ID).IsEqualTo(setoutDocument.DocumentLink.ID),
+                new Columns<Document>(x => x.ID))
+            .ToObjects<Document>().FirstOrDefault();
+        
+        try
+        {
+            var file = new FileInfo(stagingSetout.SavePath);
+            if (doc is null)
             {
-                var file = new FileInfo(stagingSetout.SavePath);
-                if (doc is null)
+                doc = new Document
                 {
-                    doc = new Document
-                    {
-                        FileName = Path.GetFileName(stagingSetout.SavePath),
-                        Data = GetData(stagingSetout.SavePath)
-                    };
-                    
-                }
-                else
-                    doc.Data = GetData(stagingSetout.SavePath);
-                doc.CRC = CoreUtils.CalculateCRC(doc.Data);
-                stagingSetout.SavePath = "";
+                    FileName = Path.GetFileName(stagingSetout.SavePath),
+                    Data = GetData(stagingSetout.SavePath)
+                };
                 
-                stagingSetout.LockedBy.ID = Guid.Empty;
-                stagingSetout.LockedBy.Synchronise(new Employee());
-                
-                file.Attributes = FileAttributes.Normal;
-                file.Delete();
-                var save = new MultiSave();
-                save.Add(typeof(Document), doc);
-                save.Add(typeof(StagingSetout), stagingSetout);
-                save.Save(null, "Reloaded / Unlocked staging setout");
-            }
-            catch (Exception ex)
-            {
-                MessageBox.Show(ex.Message);
             }
+            else
+                doc.Data = GetData(stagingSetout.SavePath);
+            doc.CRC = CoreUtils.CalculateCRC(doc.Data);
+            stagingSetout.SavePath = "";
+            
+            stagingSetout.LockedBy.ID = Guid.Empty;
+            stagingSetout.LockedBy.Synchronise(new Employee());
+            
+            file.Attributes = FileAttributes.Normal;
+            file.Delete();
+            var save = new MultiSave();
+            save.Add(typeof(Document), doc);
+            save.Add(typeof(StagingSetout), stagingSetout);
+            save.Save(null, "Reloaded / Unlocked staging setout");
         }
-
-        // protected override void Reload(Filters<StagingSetout> criteria, Columns<StagingSetout> columns, ref SortOrder<StagingSetout>? sort, Action<CoreTable?, Exception?> action)
-        // {
-        //     criteria.Add(new Filter<StagingSetout>(x => x.Archived).IsEqualTo(DateTime.MinValue));
-        //     base.Reload(criteria, columns, ref sort, action);
-        // }
-        
-        private void FilterComponent_OnFilterSelected(DynamicGridSelectedFilterSettings settings)
+        catch (Exception ex)
         {
-            _settings.Filters = settings;
-            new UserConfiguration<StagingSetoutGridSettings>().Save(_settings);
+            MessageBox.Show(ex.Message);
         }
-        
-        protected override Dictionary<string, object?> EditorValueChanged(IDynamicEditorForm editor, StagingSetout[] items, string name, object value)
-        {
-            var result = base.EditorValueChanged(editor, items, name, value);
+    }
 
-            if (name.Equals("JobLink.ID"))
-            {
-                // false here because a job has a defaultscope
-                // and we need to load the lookups before we set the default value
-                var scope = editor.FindEditor("JobScope.ID") as ILookupEditorControl;
-                if (scope != null)
-                    DefineLookups(scope,items,false); 
+    // protected override void Reload(Filters<StagingSetout> criteria, Columns<StagingSetout> columns, ref SortOrder<StagingSetout>? sort, Action<CoreTable?, Exception?> action)
+    // {
+    //     criteria.Add(new Filter<StagingSetout>(x => x.Archived).IsEqualTo(DateTime.MinValue));
+    //     base.Reload(criteria, columns, ref sort, action);
+    // }
+    
+    private void FilterComponent_OnFilterSelected(DynamicGridSelectedFilterSettings settings)
+    {
+        _settings.Filters = settings;
+        new UserConfiguration<StagingSetoutGridSettings>().Save(_settings);
+    }
+    
+    protected override Dictionary<string, object?> EditorValueChanged(IDynamicEditorForm editor, StagingSetout[] items, string name, object value)
+    {
+        var result = base.EditorValueChanged(editor, items, name, value);
+
+        if (name.Equals("JobLink.ID"))
+        {
+            // false here because a job has a defaultscope
+            // and we need to load the lookups before we set the default value
+            var scope = editor.FindEditor("JobScope.ID") as ILookupEditorControl;
+            if (scope != null)
+                DefineLookups(scope,items,false); 
 
-            }
-            
-            return result;
         }
+        
+        return result;
     }
 }