GlobalAccessSoftware icon

Dealing with ListBoxes and Collections, etc.

GlobalAccessSoftware | PRO | 05/17/17 05:45:27 PM UTC | 0 ⭐ | 808 👁️ | Never ⏰ | []
C# |

103.43 KB

|

None

|

0 👍

/

0 👎

 
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// OptionsMiscAlternate.cs//\\//\\//\\//\\//\\//
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// Global  Access  Software  InTernational//\\//
// Copyrighted (c)2013 by John P. Edwards/\\//\\
// *** Sunday, July 21, 2013 8:01:09 AM/\\//\\//
// M Saturday, July 27, 2013 10:45:09 PM//\\//\\
// ReSharper7 Approved by -JpE- v1.4.1.2x\//\\//
// Friday, August 09, 2013 11:19:04 PM\\//\\//\\
// Friday,   July 25, 2014 08:25 PM/\\//\\//\\//
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// Split out from OptionsMisc.cs\\//\\//\\//\\//
// v4.6.7.76 Jan 28 2017 Isolated to here!\\//\\
// This Source File is like 150 Lines atm.//\\//
// Including the Comments and Design Ideas\\//\\
// and everything else roughed except that//\\//
// The HelpButtonClick is pretty finished \\//\\
// codewise. Just need to complete that file\\//
// v4.6.7.78 Jan 30 2017 in Design Phase. \\//\\
// v4.6.7.87 Feb 09 2017 Early Alpha 1st phase./
// v4.6.7.95 Feb 11 2017 Alpha-Beta Stages. //\\
// I am working on the ListBox Hovers or trying/
// v4.6.7.98 Feb 11 2017 Everything works 4 AFF\
// But it's not yet hooked up to anything in IF/
// v4.6.8.23 Feb 27 2017 Touching Up Final. //\\
// v4.6.8.43 Mar 15 2017 Reworked MoveExisting./
// v4.6.9.63 Mar 26 Added "Select File" to\\//\\
// Context Menu Items along with supporting/\\//
// Methods. Tests Very Well Indeed.\//\\//\\//\\
// v4.6.9.64 Added Context Menu Item that\//\\//
// Lets the User Select a New Reports Folder//\\
// For this Data Folder. Mar 26 2017\\//\\//\\//
// v4.6.9.76 Mar 30 2017//\\//\\//\\//\\//\\//\\
// v4.6.9.77 Mar 30 Upgraded to ObjectModel!\\//
// Context Menu for Data Folders improved with\\
// v4.6.9.82 Mar 31 2017 File Print Options.\\//
// v4.6.9.87 Apr 04 2017 UpGraded Context Menus!
// v4.7.0.04 Apr 12 2017 More On The End there!
// v4.7.0.07 Apr 14 2017 Finishing ^ & DoW-Mods.
// v4.7.1.24 Apr 20 Integration & Consolidation.
// v4.7.1.31 Apr 22 Added List Restore Contexts.
// v4.7.1.35 Apr 24 and perfected them & all.
// v4.7.2.53 May 05 Restore methods almost done.
// v4.7.2.61 May 09 Backup methods nearly done.
// v4.7.3.65 May 11 Nearly Clear, Final Testing.
// v4.7.3.77 May 17 ViewAllPrefs & ViewAllAss.
// Revamped Overloads and such for DisplayResults
// & DisplayResults() to work with ViewALL-Mods.
// v4.7.3.78 Added the lil Quick-Launch Feature!
// Resources straightened out and a new Icon for
// the QS & fixed & organized right all around.
// v4.7.3.85 Adds AYS to MinVerb YesNo's, etc.
// Perfecting MoveUp-Data & Testing all more.
// v4.7.3.93 May 30 2017 Better Default Mods
// for the Selector index mods.
// v4.7.3.96 May 31 2017 Fixed ViewAllAss!
// v4.7.5.19 12Jun17 Caps a lot of mods here
// including the Backup/Restore for Both Lists
// and all the called methods therefor. i.e.
// The Big 4 and Supporting Methods Regions.
// and mostly in AppCode4 for the RecNum stuff.
// OMA now @ 2776 Lines! BackupListsAuto added.
// BLA is called from AppCode2.Restore4() now
// as part of the Scheduled Maintenance now.
// v4.7.5.20 12Jun Integration & Wipe Testings.
// v4.7.5.25 14Jun Split the Big 4 n2 the Big 2!
// with a few specific methods & reUses mostly.
// v4.7.5.28 Final Details of Formatting Code
// Files and make as readable as possible.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
// "NameSpaces" Included.
using System;
using System.IO;
using System.Linq;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
 
// Code File "Aliases" to shorten.
using IF  = WhoAreYou.InfoForm;
using AST = WhoAreYou.AppStatic;
using APS = WhoAreYou.Properties.AppSettings;
using OPS = WhoAreYou.Properties.OptionsSettings;
using AUS = WhoAreYou.Properties.AppUserSettings;
using ORS = WhoAreYou.Properties.OptionsResources;
using PMS = WhoAreYou.Properties.PrintMasterSettings;
 
namespace WhoAreYou
{
  public partial class OptionsForm // <-= NOTE!
  {
#region Alternate Folder Finder
 
    /* Design Ideas and other imagineering:
     * ************************************
     * Okay, so like this Region and Methods herein are all about the
     * AlternateFolderFinder or AFF. The ListBoxs will Allow a Collection
     * of Paths to be Stored. So I need to "hook" it into the 
     * Data and Reports TextBoxes without altering anything there,
     * but to Collect those paths, anytime there is a new one.
     * 
     * So then, I'll need to compare those to Entries and so on.
     * And I'll need Settings to store the Collections and retrieve them, etc.
     * 
     * Then, when there is a Collection of at least the Current few we can know that
     * the paths are valid or they  wouldn't be in the Data or ReportsTextBox.Text!
     * 
     * Initial Values are the good old AppDir+"\\" + Home and...
     * AppDir + "\\" + Home + "\\" + Reports
     * that the App defaults-to on startup and so forth. (AppCode4.cs)
     * 
     * Then DataSelect Button Click or Double Mouse Click on the Selected Index
     * will simply put that Entry into the Data or ReportsTextBox.text, etc.
     * 
     * Also, maybe, if the Open Button is Clicked when a Listbox Item is 
     * highlighted, it opens that folder. ***See Context Menu Items***
     * 
     * Then I guess Clicking the Select Button will basically put the Selected
     * index item into the DataTextBox.Text (or Reports L8r) and do the same
     * basic things as happen after the folderBrowser Dialog; PopulateListBoxes, etc.
     * SelectedPath returns to top of list, right below default.
     * 
     * -JpE- (I totally love this phase when there's so much potential
     *  and ideas are flowing freely and merging into real concepts and code.)
     *  Feb 01-15 2017
     *  Apr 04    2017 and nearly 1,000 lines of code later. IT'S FUCKING WONDERFUL!
     *  Much more than I'd originally envisioned, with the new Context Menu Item
     *  UpDates, at the Bottom, and so forth that all tie into everything nicely.
     *  Great Job on Creating, Designing, Writing, Testing and Upgrading Integrations.
     */
 
 
#region Collection Methods
 
    /// <summary> Add initial default paths to BOTH Collections.
    /// Called Once for Data Path, once for Reports Path.
    /// called from OptionsFormLoad(); each instance if count
    /// is less than 2.
    /// </summary>
    /// <param name="dataPath"></param>
    private void AddDefaultsToPathCollectionsLocal(bool dataPath)
    {
      AddDefaultsToPathCollections(dataPath);
      PopulateListBoxes();
    }
 
    /// <summary> Add initial default paths to BOTH Collections.
    /// True for Data Path, False for Reports Path.
    /// as of v4.7.1.24 Apr 20 2017, ReUsed by AppCode5 Class.
    /// </summary>
    /// <param name="dataPath"></param>
    public static void AddDefaultsToPathCollections(bool dataPath)
    {
      // adds defaults to initial collections...
      string path;
      // true if DataCollection, false if ReportsCollection.
      if (dataPath.Equals(true))
      {
        path =
          AUS.Default.AppDir +
          "\\" + APS.Default.Home;
        OPS.Default.dataListBoxItems.Add(path);
      }
      else
      {
        path =
          AUS.Default.AppDir +
          "\\" + APS.Default.Home +
          "\\" + PMS.Default.Reports;
        OPS.Default.reportsListBoxItems.Add(path);
      }
      OPS.Default.Save();
      // doesn't have to be created, just added to as a Setting.
    }
 
    private void AddToPathCollection(string path, bool which)
    {
      AddToPathCollectionPublic(path, which);
      PopulateListBoxes(); // NOTE! Only difference locally.
    }
    /// <summary> Grabs the current path to see...
    /// if it's in the collection and adds it to the
    /// pertinent collection when it isn't already there.
    ///  sender == true is DataList, sender == false is ReportsList.
    /// </summary><param name="path"></param>
    /// <param name="which"></param>
    public static void AddToPathCollectionPublic(string path, bool which)
    {
      if (which.Equals(true))
      {
        if (CheckForItem(path, true).Equals(false))
        {
          // check if collection is full then delete least used if it is...
          SizeCollection(true);
          if (OPS.Default.dataListBoxItems.Count > 1)
          {
            OPS.Default.dataListBoxItems.Insert(1, path);
          }
          else OPS.Default.dataListBoxItems.Add(path);
        }
        else // otherwise it already exists and we...
        {
          MoveExistingItemTo2NdInList(path, true);
        }
      }
      else // If path ^v is NOT already in collection, add it.
      {
        if (CheckForItem(path, false).Equals(false))
        {
          SizeCollection(false);
          if (OPS.Default.reportsListBoxItems.Count > 1)
          {
            OPS.Default.reportsListBoxItems.Insert(1, path);
          }
          else OPS.Default.reportsListBoxItems.Add(path);
        }
        else // otherwise it already exists and we...
        {
          MoveExistingItemTo2NdInList(path, false);
        }
      }
      OPS.Default.Save();
    }
 
    /// <summary> Item is already in the collection, 
    /// move it to 2nd Unless already 1st or 2nd(default);
    /// (i.e. Index 0 or 1 in the List.) -ed
    /// Leaves 0 and 1 alone, no changes needed.
    /// true to access dataListBoxItems,
    /// false to access reportsListBoxItems. -JpE-
    /// </summary>
    /// <param name="path"></param>
    /// <param name="which"></param>
    private static void MoveExistingItemTo2NdInList(string path, bool which)
    {
      // Find index of Item and move it to Position 1.
      // If which is true it's Data Path, if false it's Reports.
      if (which.Equals(true))
      {
        if (OPS.Default // clone 2 of 3 v4.6.8.43
          .dataListBoxItems.IndexOf(path) < 2) return;
 
        if (OPS.Default.dataListBoxItems.Count > 1)
        {
          OPS.Default.dataListBoxItems.Remove(path);
          OPS.Default.dataListBoxItems.Insert(1, path);
        }
        else OPS.Default.dataListBoxItems.Add(path);
      }
      else // NOTE: Default is always kept at Position Zero.
      {
        if (OPS.Default // clone 3 of 3
          .reportsListBoxItems.IndexOf(path) < 2) return;
 
        if (OPS.Default.reportsListBoxItems.Count > 1)
        {
          OPS.Default.reportsListBoxItems.Remove(path);
          OPS.Default.reportsListBoxItems.Insert(1, path);
        }
        else OPS.Default.reportsListBoxItems.Add(path);
      }
      //OPS.Default.Save();
    }
 
    /// <summary> Removes Items Beyond Default Item Count.
    /// p = true is Data, p = false is Reports.
    /// 
    /// v4.7.1.25 Apr 21 2017
    /// Makes Count = 49 thus 50 paths stored. (see AppSettings)
    /// </summary>
    /// <param name="p"></param>
    /// <returns></returns>
    private static void SizeCollection(bool p)
    {
      if (p.Equals(true)) // Data Code Path.
      {
        var count = OPS.Default.dataListBoxItems.Count;
        if (count > APS.Default.Count)
        {
          OPS.Default.dataListBoxItems.RemoveAt(count - 1);
        } // Remove Last Path in List if Collection is "full."
      }
      else               // Reports Code Path.
      {
        var count = OPS.Default.reportsListBoxItems.Count;
        if (count > APS.Default.Count) // testswell! // > 4
        {
          OPS.Default.reportsListBoxItems.RemoveAt(count - 1);
        }
      }
    }
 
    /// <summary> return false if path is NOT already in collection.
    /// If path "is" already in collection forget it, return true.
    /// </summary>
    /// <param name="path"></param>
    /// <param name="which"></param>
    /// <returns></returns>
    private static bool CheckForItem(string path, bool which)
    {
      // if check is false, it is not in the collection.
      if (which.Equals(true)) // it's a Data Path.
      {
        if (OPS.Default.dataListBoxItems.Contains(path)) return true;
      }
      else                   // it's a Reports Path.
        if (OPS.Default.reportsListBoxItems.Contains(path)) return true;
 
      return false;
    }
#endregion Collection Methods
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Action Methods
 
    private void PopulateListBoxes()
    {
      OPS.Default.Save();
      // Initialize and Populate both ListBoxes with appropriate collections.
      var hasno = false;
      var invalid = new Collection<string>();
      dataListBox.Items.Clear();
      reportsListBox.Items.Clear();
 
      if (OPS.Default.dataListBoxItems.Count < 1)
        AddDefaultsToPathCollectionsLocal(true);
 
      if (OPS.Default.reportsListBoxItems.Count < 1)
        AddDefaultsToPathCollectionsLocal(false);
 
      IF.CheckBothFolderCollections(); // <-= v4.7.1.33
 
      foreach (var item in OPS.Default.dataListBoxItems)
      {
        if (!ValidateItem(item, true))
        {
          hasno = true;
          invalid.Add(item);
          continue;
        }
        dataListBox.Items.Add(item);
      }
      dataListBox.SelectedIndex = OPS.Default.dataListBoxItems // v4.7.0.03
        .IndexOf(OPS.Default.dataListBoxItems.Contains(PreviouslySelectedDir1)
        ? PreviouslySelectedDir1 : OPS.Default.PrefRootDir);
      if (hasno) RemoveInvalidFolders(true, invalid);
      hasno = false;
      invalid.Clear();
 
      // And do similarly for reportsListBox.Items.
      if (OPS.Default.reportsListBoxItems.Count < 1)
      {
        OPS.Default.reportsListBoxItems
          .Add(ReportsTextBox.Text);
        OPS.Default.Save();
      }
      foreach (var item in OPS.Default.reportsListBoxItems)
      {
        if (!ValidateItem(item, false))
        {
          hasno = true;
          invalid.Add(item);
          continue;
        }
        reportsListBox.Items.Add(item);
      }
 
      reportsListBox.SelectedIndex = OPS.Default.reportsListBoxItems // v4.7.0.03
        .IndexOf(OPS.Default.reportsListBoxItems.Contains(PreviouslySelectedDir2)
        ? PreviouslySelectedDir2 : OPS.Default.PrefReportsDir);
      if (hasno) RemoveInvalidFolders(false, invalid);
    }
 
    /// <summary> Select Previously Selected Index Mods; Set Previous.
    /// v4.7.0.03 v  PSD1&2C vars Used Above ONLY. Set to Prefs on FormLoad.
    /// These EVENT Handlers are called on changes and these vars only change herein.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void SelectedIndex1Change(object sender, EventArgs e)
    {
      PreviouslySelectedDir1 =
        dataListBox.SelectedItem.ToString();
    }
 
    private void SelectedIndex2Change(object sender, EventArgs e)
    {
      PreviouslySelectedDir2 =
        reportsListBox.SelectedItem.ToString();
    }
 
    private void RemoveInvalidFolders
      (bool data, ICollection<string> list)
    {
      if (list.Count < 1) return;
      var default1 = OPS.Default.dataListBoxItems[0];
      var default2 = OPS.Default.reportsListBoxItems[0];
 
      if (data)
      {
        if (list.Contains(default1)) list.Remove(default1);
        foreach (var item in list)
          OPS.Default.dataListBoxItems.Remove(item);
      }
      else
      {
        if (list.Contains(default2)) list.Remove(default2);
        foreach (var item in list)
          OPS.Default.reportsListBoxItems.Remove(item);
      }
      PopulateListBoxes();
    }
 
    /// <summary> Verify Folder Exists and
    /// in the case of DataFolder, that data files exist.
    /// </summary>
    /// <param name="item"></param>
    /// <param name="path"></param>
    /// <returns></returns>
    private static bool ValidateItem(string item, bool path)
    {
      var test = false;
      if (path.Equals(true)) // Data Folder.
      {
        if (Directory.Exists(item)
          && HasDataFiles(item)) test = true;
      }
      else // Reports Folder.
      {
        if (Directory.Exists(item)) test = true;
      }
      return test;
    }
 
    /// <summary> Make Sure Data Folder has data files.
    /// Rev v4.7.1.24 April 20 2017 and made public.
    /// </summary>
    /// <param name="folder"></param>
    /// <returns></returns>
    public static bool HasDataFiles(string folder)
    {
      return
        (from file in Directory.EnumerateFiles(folder)
         let extension = Path.GetExtension(file)
         where !string.IsNullOrEmpty(extension)
           && !string.IsNullOrEmpty(file)
         where extension.Equals(APS.Default.Ext)
           && !file.Contains("Bac_")
           && !file.Contains(APS.Default._drf)
           && !file.Equals(APS.Default.NewFile)
         select extension).Any();
    }
 
    private void DataSelectButtonClick(object sender, EventArgs e)
    {
      var path = dataListBox.Text;
      // NOTE: Every time a Path is reSelected, it needs be put back on top.
      var test = OPS.Default.dataListBoxItems.IndexOf(path);
      if (test > 1) // if default path or 2nd leave it alone.
      {
        MoveExistingItemTo2NdInList(path, true);
      }
      // Now put that path into the dataTextBox.Text and Save Changes.
      folderBrowser.SelectedPath = path;
      DataChanges();
    }
 
    private void ReportsSelectButtonClick
      (object sender, EventArgs e)
    {
      var path = reportsListBox.Text;
      var test = OPS.Default.reportsListBoxItems.IndexOf(path);
      if (test > 1) MoveExistingItemTo2NdInList(path, false);
      folderBrowser.SelectedPath = path;
      ReportsChanges();
    }
#endregion Action Methods
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Context Menu Items
 
    /* DOC:
     *  \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
     * The Context Menu 1 items and true args are DataFolder
     * Specific and the Context Menu 2 items and false args
     * are Reports Folder Specific throughout.
     * 
     * NOTE: Numerous Updates were done after the initial code.
     * See notes and Docs for each Below.
     *  \\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
     */
 
 
#region Original Context Menu Items
 
    private void ViewToolStrip1MenuItemClick(object sender, EventArgs e)
    {
      MessageBox.Show(dataListBox.SelectedItem.ToString());
    }
 
    private void OpenToolStrip1MenuItemClick(object sender, EventArgs e)
    {
      if (!OPS.Default.MiniVerb && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog("Open This Folder?")) return;
      var folder = dataListBox.SelectedItem.ToString();
      AST.OpenFolder(folder);
    }
 
    private void RemoveToolStrip1MenuItemClick(object sender, EventArgs e)
    {
      var item = dataListBox.SelectedIndex;
      if (item.Equals(0))
      {
        MessageBox.Show(ORS.OF_Remove);
        return;
      }
      if (item.Equals(1))
      {
        MessageBox.Show(ORS.OF_Reselect);
        return;
      }
      if (!OPS.Default.MiniVerb)// && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog(string.Format(
          "Remove this Folder from the List?\n{0}",
            dataListBox.Items[item]))) return;
 
      OPS.Default.dataListBoxItems.RemoveAt(item);
      PopulateListBoxes();
    }
 
    private void ClearToolStrip1MenuItemClick(object sender, EventArgs e)
    {
      var test = OPS.Default.dataListBoxItems.Count;
      if (test < 2) return; // Keep The Default.
      if (!OPS.Default.MiniVerb)// && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog("Clear This Entire List?")) return;
 
      OPS.Default.dataListBoxItems.Clear();
      AddDefaultsToPathCollectionsLocal(true);
      DataTextBox.Text =
        OPS.Default.dataListBoxItems[0];
    }
 
    private void OpenToolStrip2MenuItemClick(object sender, EventArgs e)
    {
      if (OPS.Default.reportsListBoxItems.Count < 2) return;
      if (!OPS.Default.MiniVerb && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog("Open This Folder?")) return;
      var folder = reportsListBox.SelectedItem.ToString();
      AST.OpenFolder(folder);
    }
 
    private void RemoveToolStrip2MenuItemClick(object sender, EventArgs e)
    {
      var item = reportsListBox.SelectedIndex;
      if (item.Equals(0))
      {
        MessageBox.Show(ORS.OF_Remove);
        return;
      }
      if (item.Equals(1))
      {
        MessageBox.Show(ORS.OF_Reselect);
        return;
      }
      if (!OPS.Default.MiniVerb)
        if (!AST.YesNoDialog(string.Format(
          "Remove this Folder from the List?\n{0}",
            reportsListBox.Items[item]))) return;
 
      OPS.Default.reportsListBoxItems.RemoveAt(item);
      PopulateListBoxes();
    }
 
    private void ClearToolStrip2MenuItemClick(object sender, EventArgs e)
    {
      if (OPS.Default.reportsListBoxItems.Count < 2) return;
      // ^ Keep The Default.
      if (!OPS.Default.MiniVerb) //&& !OPS.Default.AreYouSure
        if (!AST.YesNoDialog("Clear This Entire List?")) return;
      OPS.Default.reportsListBoxItems.Clear();
      AddDefaultsToPathCollectionsLocal(false);
      ReportsTextBox.Text = OPS.Default.reportsListBoxItems[0];
    }
 
    private void ViewToolStripMenuItem2Click(object sender, EventArgs e)
    {
      MessageBox.Show(reportsListBox.SelectedItem.ToString());
    }
#endregion Original Context Menu Items
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region v4.6.9.67 Mar 27 2017
 
    private void SelectFileToolStrip1MenuItemClick
      (object sender, EventArgs e)
    {
      if (!OPS.Default.MiniVerb && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog(
          "Select a Data File for this Folder?")) return;
 
      // Now do it!
      var dir = dataListBox.SelectedItem.ToString();
      if (!Directory.Exists(dir) || !HasDataFiles(dir))
      { PopulateListBoxes(); return; }
 
      var files = GetDataFileList(dir);
      // v4.7.3.93 May 30 2017 vvvvvvv
      var index = 0;
      var test = GetPrefFileName(dir);
      if (files.Contains(test))
        index = files.IndexOf(test);
      else
        if (files.Contains(OPS.Default.PrefFileName))
          index = files.IndexOf(OPS.Default.PrefFileName);
        else
          if (files.Contains(AUS.Default.FileName))
            index = files.IndexOf(AUS.Default.FileName);
          else
            if (files.Contains(PMS.Default.Bac_PrefFileName))
              index = files.IndexOf(PMS.Default.Bac_PrefFileName);
            else
              if (files.Contains(APS.Default.defaultFilename))
                index = files.IndexOf(APS.Default.defaultFilename);
      // Selected index Mods    ^^^^^^^^^
 
      var size = AUS.Default.OMA_FileSelect_Size;
      var location = AUS.Default.OMA_FileSelect_Location;
      var choice = SelectOne(files, ref size, ref location, "", index);
      AUS.Default.OMA_FileSelect_Size = size;
      AUS.Default.OMA_FileSelect_Location = location;
      AUS.Default.Save();
 
      if (string.IsNullOrEmpty(choice)
        || !File.Exists(dir + "\\" + choice)) return;
      if (OPS.Default.dataListBoxItems.IndexOf(dir).Equals(1))
      { OPS.Default.PrefFileName = FileName = choice; }
      RememberThis2(choice, dir);
      if (!OPS.Default.MiniVerb) Feedback();
    }
 
    private static void Feedback()
    {
      const string
        text = "Your Preferences Have Been Saved.";
      MessageBox.Show(text);
    }
 
    /// <summary> Get List of strings of DataFile Names
    /// That Exist on this particular Directory. Linq vers.
    /// </summary>
    /// <returns></returns>
    public static Collection<string> GetDataFileList(string folder)
    {
      #region Was
      //// optimized only after testing and noting original.
      //var list = new List<string>();
      //foreach (var file in Directory.EnumerateFiles(
      //  OPS.Default.PrefRootDir))
      //{
      //  var name = Path.GetFileName(file);
      //  var extension = Path.GetExtension(file);
      //  if ( string.IsNullOrEmpty(extension)
      //    || string.IsNullOrEmpty(name)
      //    || !extension.Equals(APS.Default.Ext)
      //    || name.Contains(APS.Default._drf)
      //    || name.Equals(APS.Default.NewFile)
      //    || name.Contains("Bac_")) continue;
 
      //  list.Add(name);
      //}
      //return list;
      //// Converted to Linq it's...
      #endregion Was
      return
        new Collection<string>((from file in Directory.EnumerateFiles(folder)
          let name = Path.GetFileName(file)
          let extension = Path.GetExtension(file)
          where !string.IsNullOrEmpty(extension)
            && !string.IsNullOrEmpty(name)
            && extension.Equals(APS.Default.Ext)
            && !name.Contains(APS.Default._drf)
            && !name.Equals(APS.Default.NewFile)
            && !name.Contains("Bac_")
          select name).ToList());
    }
 
    // write file to dir indicating pref Filename for this Dir.
    private static void RememberThis2(string filename, string dir)
    {
      var
        contents =
          filename +
            "\n" + GetStoredReportsDirPref(dir) +
              "\nOMA_RememberThis2();";
      var
        file = dir + "\\" + APS.Default.PrefFile;
 
      File.WriteAllText(file, contents);
    }
 
    // Get it & put it right back in with different filename.
    private static string GetStoredReportsDirPref(string dir)
    {
      var pref = OPS.Default.PrefReportsDir;
      var file = dir + "\\" + APS.Default.PrefFile;
 
      if (File.Exists(file))
      {
        var path = File.ReadAllText(file).Split('\n')[1];
        // grabs second line of file only.
        if (!path.Contains("()")
          && !path.Contains(";")
          && Directory.Exists(path)
          ) pref = path;
      }
      return pref;
    }
 
    // v4.6.9.67 Mar 27 2017
    private void SelectReportsFolderToolStrip1MenuItemClick
        (object sender, EventArgs e)
    {
      if (!OPS.Default.MiniVerb && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog(
          "Select a Reports Folder" +
          " for this Data Folder?")) return;
      var dir = dataListBox.SelectedItem.ToString();
      var list = OPS.Default.reportsListBoxItems;
      var relist = new Collection<string>(); // <-= v4.6.9.77!
      foreach (var path in list) // Convert from Specialized String Collection
      { relist.Add(path); } // to a Generic ObjectModel.Collection<T>
      // SelectorForm Use and Example thereof.
 
      // v4.7.3.95 Index Mods extended to these.
      var index = 0;
      var test  = GetStoredReportsDirPref(dir);
      if (relist.Contains(test))
        index   = relist.IndexOf(test);
      else
        if (relist.Contains(OPS.Default.PrefReportsDir))
          index = relist.IndexOf(OPS.Default.PrefReportsDir);
        else
          if (relist.Contains(PMS.Default.ReportsFolder))
            index = relist.IndexOf(PMS.Default.ReportsFolder);
      // else default to the index[0] default.
      // ^ v4.7.3.93 May 30 2017
 
      const string text = "Select a Reports Folder:";
      var size = AUS.Default.OMA_ReportsSelect_Size;
      var locate = AUS.Default.OMA_ReportsSelect_Location;
      var selected = SelectOne(relist, ref size, ref locate, text, index);
      AUS.Default.OMA_ReportsSelect_Size = size;
      AUS.Default.OMA_ReportsSelect_Location = locate;
      AUS.Default.Save();
      if (string.IsNullOrEmpty(selected)) return;
 
      // v4.6.9.87 Apr 04 2017 - All Four Possibles Tested.
      // If it's the default data dir it moves the pref reports
      // folder to the 2nd-position* or leaves it alone if it's the
      // default or pref reports dir already. (*2nd in the list, index[1].)
      if (dir.Equals(OPS.Default.PrefRootDir))
      {
        if (selected != list[0])
        {
          MoveExistingItemTo2NdInList(selected, false);
          PopulateListBoxes();
        }
        ReportsTextBox.Text =
          PreviouslySelectedDir2 =
            OPS.Default.PrefReportsDir = selected;
      }
      RememberThis3(selected, dir);
      if (!OPS.Default.MiniVerb) Feedback();
    }
 
    // write file to dataDir indicating selected ^
    private void RememberThis3
      (string selectedReportsDir, string dataDir)
    {
      var
        contents = GetPrefFileName(dataDir) +
                   "\n" + selectedReportsDir +
                   "\n" + "OMA_RememberThis3();";
      var
        prefFile = dataDir + "\\" +
                   APS.Default.PrefFile;
 
      File.WriteAllText(prefFile, contents);
    }
 
    // Get it & put it right back in ^ with different Reports Pref.
    private string GetPrefFileName(string dir)
    {
      var pref = FileName; // as default value.
      var file = dir + "\\" + APS.Default.PrefFile;
 
      if (File.Exists(file))
      {
        var name = File.ReadAllText(file).Split('\n')[0];
        // Reads First Line of File Only. ^
        if (!string.IsNullOrEmpty(name)
          && File.Exists(dir + "\\" + name)) pref = name;
      }
      return pref;
    }
#endregion v4.6.9.67 Mar 27 2017
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Upgrade 4.6.9.87 Apr 04 2017
 
    /* Upgrade adds two context menu items, to each context menu,
     * For Move-Up & Move-Down of selected item. 1st item cannot
     * be moved. 2nd Item cannot be moved. If 3rd item is moved to 2nd
     * then we prompt them to make this the prefFolder or back out,
     * leaving things be. Only if 3rd item is moved up AND made the pref
     * does the 2nd (Pref) item fall to 3rd. Nothing can be moved higher than
     * 2nd, the default stays on top no matter what. The pref is 2nd no matter
     * what, except if default path. The bottom item cannot be moved down.
     * Folder must exist. Data folders must contain data files.
     */
 
    /// <summary> The ProtoType For All The Below.
    /// Event handler for the Move Up Context Menus. Item
    /// selected is moved up the list unless already 1st or 2nd.
    /// If 3rd is moved up it requires approval to become Pref.
    /// 
    /// See Called Methods below, some shared and so forth.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveUpToolStrip1MenuItemClick(object sender, EventArgs e)
    { // Data Collection
      if (dataListBox.Items.Count < 3)
      {
        MessageBox.Show(ORS.OMA_MoveItem);
        return; // Remove Short Lists from the equation.
      }
      var dir = dataListBox.SelectedItem.ToString();
      if (!Directory.Exists(dir) || !HasDataFiles(dir))
      {
        OPS.Default.dataListBoxItems.Remove(dir);
        PopulateListBoxes();
        MessageBox.Show(string.Format(
          "The Directory:\n{0}\n\nDoes NOT Exist, or Data Files\n" +
          " could no longer be found on it.\n\n" +
          "It was removed from the list.", dir));
        return; // Eliminate Non Existent Folders.
      }
      var index = OPS.Default.dataListBoxItems.IndexOf(dir);
      if (index < 2)
      { MessageBox.Show(ORS.OMA_Cannot); return; }
      if (index.Equals(2))
      { // 3rd Item needs approval to move up.
        if (!MakeThisThePreference(dir, true)) return;
      }
      // A Last Chance to Abort.
      if ( !OPS.Default.MiniVerb
        && !OPS.Default.AreYouSure
        && !index.Equals(2))
          if (!AST.YesNoDialog(ORS.OMA_Up)) return;
 
      // Now do it!
      MoveData(true, index);
      if (index.Equals(2))
      {
        // Make it the Pref
        folderBrowser.SelectedPath = dir;
        DataChanges();
      }
      else
        PopulateListBoxes();
    }
 
    private void MoveUpToolStrip2MenuItemClick(object sender, EventArgs e)
    {
      // Reports Collection
      if (reportsListBox.Items.Count < 3)
      {
        MessageBox.Show(ORS.OMA_MoveItem);
        return; // Remove Short Lists from the equation.
      }
      var dir = reportsListBox.SelectedItem.ToString();
      if (!Directory.Exists(dir))
      {
        OPS.Default.reportsListBoxItems.Remove(dir);
        PopulateListBoxes();
        MessageBox.Show(string.Format(
          "The Directory:\n{0}\n\n" +
          "Does NOT Exist and was removed from the list.", dir));
        return; // Eliminate Non Existent Folders.
      }
      var index = OPS.Default.reportsListBoxItems.IndexOf(dir);
      if (index < 2) { MessageBox.Show(ORS.OMA_Cannot); return; }
      if (index.Equals(2))
      { // 3rd Item needs approval to move up.
        if (!MakeThisThePreference(dir, false)) return;
      }
      // A Last Chance to Abort.
      if ( !OPS.Default.MiniVerb
        && !OPS.Default.AreYouSure
        && !index.Equals(2))
         if (!AST.YesNoDialog(ORS.OMA_Up)) return;
 
      // Now do it!
      MoveReports(true, index);
      if (index.Equals(2))
      {
        // Making it the Pref if now 2nd in List.
        folderBrowser.SelectedPath = dir;
        ReportsChanges();
      }
      else
        PopulateListBoxes();
    }
 
    /// <summary> Event Handler for Move Down Context Menu Item
    /// This version for the Data List. Clone below for Reports.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MoveDownToolStrip1MenuItemClick(object sender, EventArgs e)
    {
      // Data Collection
      var count = dataListBox.Items.Count;
      if (count < 3)
      { // Remove Short Lists from the equation.
        MessageBox.Show(ORS.OMA_MoveItem);
        return;
      }
      var dir = dataListBox.SelectedItem.ToString();
      if (!Directory.Exists(dir) || !HasDataFiles(dir))
      {
        OPS.Default.dataListBoxItems.Remove(dir);
        MessageBox.Show(string.Format(
          "The Directory:\n{0}\n\nDoes NOT Exist, or Data Files\n" +
          " could no longer be found on it.\n\n" +
          "It was removed from the list.", dir));
        return; // Eliminate Non Existent Folders.
      }
      var index = OPS.Default.dataListBoxItems.IndexOf(dir);
      if (index < 2)
      {
        MessageBox.Show(ORS.OMA_Cannot);
        return; // Remove Items 1 and 2 from the equation. ^
      }
      if (index + 1 == count)
      {
        MessageBox.Show(ORS.OMA_Last);
        return; // Can't Move Last item Down Msg.
      }
      if (!OPS.Default.MiniVerb && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog(ORS.OMA_Down)) return;
      // Last Chance to BackOut.
      // And finally, if everything above checks out, Move it.
      MoveData(false, index);
      PopulateListBoxes();
    }
 
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
    // Design Algorithm - Graphic for Move Down visualization.
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
    // index[0] = item1 can't be moved. ***Handled***
    // index[1] = item2 can't be moved. ***Handled***
    // index[2] = item3 can be moved down, by removing and inserting.
    // index[N] = itemN etc, etc. ^^^         ^^^^^^^^^^^^^^^^^^
    // index[N] = by removing and inserting ***Handled*** v
    // index[N]   by removing and inserting ***Handled*** v for N iterations.
    // index[x] = item-x 3rd from End can be moved, by removing and inserting.
    // index[y] = item-y 2nd from End can be moved, by removing & ADDING ONLY! ***OK***
    // index[z] = item-z Last item can't be moved down. ***Handled***
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
    private void MoveDownToolStrip2MenuItemClick(object sender, EventArgs e)
    {
      // Reports Collection
      var count = reportsListBox.Items.Count;
      if (count < 3)
      { // Remove Short Lists from the equation.
        MessageBox.Show(ORS.OMA_MoveItem);
        return;
      } // <-= Show msg, do Nothing. ^
      var dir = reportsListBox.SelectedItem.ToString();
      if (!Directory.Exists(dir))
      {
        OPS.Default.reportsListBoxItems.Remove(dir);
        MessageBox.Show(string.Format(
          "The Directory:\n{0}\n\nDoes NOT Exist, or Data Files\n" +
          " could no longer be found on it.\n\n" +
          "It was removed from the list.", dir));
        return; // Eliminate Non Existent Folders.
      }
      var index = OPS.Default.reportsListBoxItems.IndexOf(dir);
      if (index < 2)
      {
        MessageBox.Show(ORS.OMA_Cannot);
        return; // Remove Items 1 and 2 from the equation.
      }
      if (index + 1 == count)
      {
        MessageBox.Show(ORS.OMA_Last);
        return; // Can't Move Last item Down Msg.
      }
      if (!OPS.Default.MiniVerb && !OPS.Default.AreYouSure)
        if (!AST.YesNoDialog(ORS.OMA_Down)) return;
      // Last Chance to BackOut if Not MiniVerb or AYS.
      // And finally, if everything above checks out, Move it.
      MoveReports(false, index);
      PopulateListBoxes();
    }
 
    /// <summary> Moves Data List Items Up or Down.
    /// Clone below does the same for the Reports List.
    /// </summary>
    /// <param name="up"></param>
    /// <param name="index"></param>
    private static void MoveData(bool up, int index)
    {
      var add = false;
      var dir = OPS.Default.dataListBoxItems[index];
      var count = OPS.Default.dataListBoxItems.Count;
      OPS.Default.dataListBoxItems.RemoveAt(index);
      if (up) index--;
      else
      { // if down...
        if (index + 2 == count) add = true;
        index++; // ^ 2nd to last has to be added not inserted. v
      }
      if (add) OPS.Default.dataListBoxItems.Add(dir);
      else OPS.Default.dataListBoxItems.Insert(index, dir);
    }
    private static void MoveReports(bool up, int index)
    {
      var add = false;
      var dir = OPS.Default.reportsListBoxItems[index];
      var count = OPS.Default.reportsListBoxItems.Count;
      OPS.Default.reportsListBoxItems.RemoveAt(index);
      if (up) index--;
      else
      { // down...
        if (index + 2 == count) add = true;
        index++;
      }
      if (add) OPS.Default.reportsListBoxItems.Add(dir);
      else OPS.Default.reportsListBoxItems.Insert(index, dir);
    }
 
    /// <summary> Specialized Dialog Gets Approval for Preference Setting.
    /// Used by both Reports and Data Move Up Methods. Not needed in down.
    /// </summary>
    /// <param name="dir"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    private static bool MakeThisThePreference(string dir, bool data)
    {
      // New conditional v4.7.3.83
      if (OPS.Default.MiniVerb) return true;
 
      const string title =
        "Make This the Preference?";
      var text       = "Your New Reports Directory Preference.";
      if (data) text = "Your New Data-Directory-Preference.";
 
      return
        MessageBox.Show(string.Format(
          "This will make:\n{0}\n\n" + text +
          "\n\nAre You Sure?", dir), title,
          MessageBoxButtons.YesNo,
          MessageBoxIcon.Question,
          MessageBoxDefaultButton.Button2
        ).Equals(DialogResult.Yes);
    }
#endregion Upgrade 4.6.9.87 Apr 04 2017
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Upgrade v4.7.1.23 Upgrade SubSection Apr 19 2017
 
    private void RestoreOldPrefsClick(object sender, EventArgs e)
    {
      if (!OPS.Default.MiniVerb
        && !OPS.Default.AreYouSure)
          if (!AST.YesNoDialog(
            "Bring Back All preference files?")) return;
 
      var pref = APS.Default.PrefFile;
      foreach (var item in
        OPS.Default.dataListBoxItems)
      {
        if (!Directory.Exists(item)) continue;
        var source = item + "\\" + "old" + pref;
        if (!File.Exists(source)) continue;
        var destin = item + "\\" + pref;
        if (File.Exists(destin))
        {
          if ( !OPS.Default.MiniVerb
            && !OPS.Default.AreYouSure)
              if (!AST.YesNoDialog(
                "Replace Existing preference file?"))
            continue;
          File.Delete(destin);
        }
        File.Move(source, destin);
      }
    }
 
    private void WipePrefsClick(object sender, EventArgs e)
    {
      int mover;
      bool preserver;
      if (!OPS.Default.MiniVerb)// && !OPS.Default.AreYouSure)
      {
        const string
          text1 = "Clear ALL preference files from entire\n" +
                  "Data Folder collection?",
          text2 = "This is not recommended.\n\n" +
                  "Do you really need to start fresh?",
          text3 = "Do you want to preserve the\n" +
                  "preferences for the default Directory?",
          text4 = "Rename instead of Delete,\n" +
                  "So they can be restored if needed?";
        if (!OPS.Default.AreYouSure)
          if (!AST.YesNoDialog(text1)) return;
        if (!AST.YesNoDialog(text2)) return;
        preserver = OPS.Default.AreYouSure
          || AST.YesNoDialog(text3);
        mover = AST.YesNoDialog(text4) ? 1 : 0;
      } // v made reUsable v4.7.1.23br
      else { preserver = true; mover = 1; }
 
      BackupPreferences(preserver, mover, false);
    }
 
    private void
      BackupAllPrefsToolStripMenuItemClick
      (object sender, EventArgs e)
    {
      if (!OPS.Default.MiniVerb)
        if (!AST.YesNoDialog(
          "Backup ALL preference files,\nOver Writing " +
          "any previous backups...\n\nAre You Sure?")) return;
      BackupPreferences(false, 2, true);
      ShowResult(2);
    }
 
    /// <summary> This 1 overload is not really connected
    /// to the others of nearly the same name here, which are,
    /// for the most part, interconnected and cross dependant.
    /// </summary>
    /// <param name="moveIt"></param>
    private static void ShowResult(int moveIt)
    {
      if (OPS.Default.MiniVerb) return;
      var msg = "";
      if (moveIt < 0
         || moveIt > 2) msg = "Error in OMA!";
      if (moveIt.Equals(0)) msg = "All Preference Files Have Been Deleted.";
      if (moveIt.Equals(1)) msg = "All Preference Files Have Been ReNamed.";
      if (moveIt.Equals(2)) msg = "All Preference Files Have Been Backed up.";
      MessageBox.Show(msg);
    }
 
    /// <summary> ReWritten to accomodate both of the above calls, etc.
    /// v4.7.1.23 Apr 19 2017 Could be called elsewhere:
    /// Also Called from Restore3() if Scheduled Maint is due.
    /// </summary>
    /// <param name="preserve"></param>
    /// <param name="moveIt"></param>
    /// <param name="auto"></param>
    public static void
      BackupPreferences(bool preserve, int moveIt, bool auto)
    {
      var pref = APS.Default.PrefFile;
      foreach (var dir in OPS.Default
        .dataListBoxItems.Cast<string>()
        .Where(Directory.Exists))
      {
        if (preserve.Equals(true))
        { preserve = false; continue; }
 
        var source = dir + "\\" + pref;
        var destin = dir + "\\" + "old" + pref;
        if (!File.Exists(source)) continue;
        if (File.Exists(destin))
        {
          if ( !OPS.Default.MiniVerb
            && !OPS.Default.AreYouSure
            && !auto)
              if (!AST.YesNoDialog(
                "Delete old preference backup?"))
                  continue;
          File.Delete(destin);
        }
        if (moveIt == 0) File.Delete(source);
        if (moveIt == 1) File.Move(source, destin);
        if (moveIt == 2) File.Copy(source, destin);
      }
      if (!auto) ShowResult(moveIt);
    }
#endregion subregion v4.7.1.23 Upgrade SubSection
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
    
#region Upgrade 4.7.3.73 Updates older & adds new "View-All Options".
 
    // ContextMenuStrip1 Item for Data Dirs.
    private void ViewPrefsToolStrip1MenuItemClick(object sender, EventArgs e)
    {
      const string
        text1 = "The Reports Folder Associated with this Data Folder is:",
        text2 = "The File Name Associated with this Data Folder is:";
      string
        dir   = dataListBox.SelectedItem.ToString(),
        text3 = "",
        test1 = OPS.Default.PrefRootDir,
        filename = GetPrefFileName(dir),
        reports  = GetStoredReportsDirPref(dir);
      if (dir.Equals(test1)) text3 =
        "\nThis is your Currently Preferred Folder and Data File.";
      var msg = string.Format(
        text1 + "\n{0}\n\n" + text2 + "\n{1}\n" + text3,
        reports, filename);
      DisplayResults(msg,"");
    }
 
    // Upgrade v4.7.3.71 May 17 2017,
    // Similar to above but foreach item in DataListBox.
    private void ViewAllPrefsClick(object sender, EventArgs e)
    {
      const string
        title   = "View ALL Preferences:",
        text1   = "The Reports Folder Associated with this Data Folder is:",
        text2   = "The File Name Associated with this Data Folder is:";
      var text  = "";
      var pref  = OPS.Default.PrefRootDir;
      var list  = OPS.Default.dataListBoxItems;
      foreach (var dir in list)
      {
        var top = string.Format("Results for:\n{0}\n\n", dir);
        var msg = "";
        if (dir.Equals(pref)) msg =
          "This is your Currently Preferred Folder and Data File.\n\n";
        msg     = top + msg;
        text   += string.Format(msg + text1 +
          "\n{0}\n\n" + text2 + "\n{1}\n\n\n",
          GetStoredReportsDirPref(dir), GetPrefFileName(dir));
      }
      var size  = AUS.Default.OMA_D1_Size;
      var loca  = AUS.Default.OMA_D1_Loca;
        DisplayResults(text, title, ref size, ref loca);
      AUS.Default.OMA_D1_Size = size;
      AUS.Default.OMA_D1_Loca = loca;
      AUS.Default.Save();
    }
 
    /// <summary> These are an interconnected group of
    /// overloaded methods to handle various needs.
    /// This one defaults to a Title of "View Preferences"
    /// and calls the next one down and so on.
    /// Combines: DisplayResult, DisplayResults & DisplayOutCome.
    /// if title is empty default as shown.
    /// This one has it's own Settings for Form Size & Location.
    /// </summary>
    /// <param name="text"></param>
    /// <param name="title"></param>
    private static void DisplayResults(string text, string title)
    {
      if (string.IsNullOrEmpty(title)) title = "View Preferences:";
 
      var size = AUS.Default.OMA_DOC_Size;
      var loca = AUS.Default.OMA_DOC_Loc;
        DisplayResults(text, title, ref size, ref loca);
      AUS.Default.OMA_DOC_Size = size;
      AUS.Default.OMA_DOC_Loc  = loca;
      AUS.Default.Save();
    }
 
    /// <summary> Original v4.6.9.95 Apr 07 2017 
    /// Given a List of two strings, each, in a Generic Dictionary Collection,
    /// Call the common GetDisplayString() and then the DisplayResults();
    /// Rebuilt with OverLoads above for ViewAllAssociations v4.7.3.73 May 15
    /// It directly calls the Mother Method of them all below the next one,
    /// As does the next one.
    /// </summary>
    /// <param name="dic"></param>
    private void DisplayResults(Dictionary<string, string> dic)
    {
      var dir  = reportsListBox.SelectedItem.ToString();
      var text = GetDisplayString(dic, dir);
      var size = AUS.Default.OMA_Display_Size;
      var loca = AUS.Default.OMA_Display_Loc;
      const string title = "";
        DisplayResults(text, title, ref size, ref loca);
      AUS.Default.OMA_Display_Size = size;
      AUS.Default.OMA_Display_Loc  = loca;
      AUS.Default.Save();
    }
 
    /// <summary> This one accepts the Collection of Dictionaries for
    /// ViewAllAssociations(); Has it's own special Size & Location Settings.
    /// It directly calls the Mother Method of them all below this one.
    /// NOTE: "var x = ..." below does a ton of work,
    /// & faster because instead of a loop it's a LINQ query!
    /// </summary>
    /// <param name="listOfLists"></param>
    private static void DisplayResults
      (IEnumerable<Dictionary<string, string>> listOfLists)
    {
      #region was
      //var i = 0;
      //var x = "";
      //foreach (var dic in listOfLists)
      //  x += GetDisplayString(dic, OPS.Default.reportsListBoxItems[i++]);
      #endregion was
      var i = 0;
      var x = listOfLists.Aggregate("", (current, dic) => current   +
        GetDisplayString(dic, OPS.Default.reportsListBoxItems[i++]) +
        "========================");
 
      const string t = "";
      var s = AUS.Default.OMA_D4_S;
      var l = AUS.Default.OMA_D4_L;
        DisplayResults(x, t, ref s, ref l);
      AUS.Default.OMA_D4_S = s;
      AUS.Default.OMA_D4_L = l;
      AUS.Default.Save();
    }
 
    /// <summary> This overload is where all end up.
    /// It allows for total flexibility of usages for all args.
    /// While providing critical defaults to reduce duplicity.
    /// if title is empty it defaults to:
    /// "Folder Associations Information:"
    /// </summary>
    /// <param name="x"></param>
    /// <param name="t"></param>
    /// <param name="s"></param>
    /// <param name="l"></param>
    private static void DisplayResults
      (string x, string t, ref Size s, ref Point l)
    {
      if (string.IsNullOrEmpty(t)) t =
        "Folder Associations Information:";
      using (var f = new ShowMeForm(x, t))
      {
        f.Size     = s;
        f.Location = l;
          f.ShowDialog();
        l = f.Location;
        s = f.Size;
      }
    }
 
    /// <summary> This was split out so it can be used by both
    /// the View2Associations and the ViewAllAssociations: v4.7.3.75
    /// Added the string dir arg to the sig to interface it with both.
    /// </summary>
    /// <param name="dic"></param>
    /// <param name="dir"></param>
    /// <returns></returns>
    private static string GetDisplayString
      (Dictionary<string, string> dic, string dir)
    { // Sweet! Great integration.
      #region Was
      //foreach (var pair in list)
      //{
      //  // Concatenate the text string and show it.
      //  text += "The Data Folder:\n" + pair.Key +
      //    "\n\nWhich is set to the Data file: \n" +
      //    pair.Value + "\n\n";
      //}
      #endregion Was
      var
        text = string.Format("\nResults for: {0}\n\n" +
          "The following currently use this Reports Folder:\n\n", dir);
      return
        dic.Aggregate(text, (current, pair) => current +
          ("The Data Folder:\n" + pair.Key +
            "\n\nWhich is set to the Data file: \n" +
              pair.Value + "\n\n"));
    }
 
    /// <summary> Upgrade v4.7.3.96 May 30 2017
    /// Similar to the View2Ass but foreach item in ReportsListBox.
    /// Design hopped up the Engine below for usage here by splitting
    /// the existing EventHandler v into two parts,
    /// the 2nd of which (the engine) I can reuse here.
    /// NOTE use of Collection of Dictionaries. Very powerful and
    /// especially when you consider that Dictionaries are Generic!
    /// this calls a special overload of DisplayResults(list);
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ViewAllAssociationsClick(object sender, EventArgs e)
    {
      var none = new Collection<string>();
      var list = new Collection<Dictionary<string, string>>();
      var dirs = OPS.Default.reportsListBoxItems;
      foreach (var dir in dirs.Cast<string>()
        .Where(dir => !string.IsNullOrEmpty(dir)
          && Directory.Exists(dir)))
      {
        var dict = new Dictionary<string, string>();
        View2AssociationsEngine(dir, ref dict, true);
        if (dict.Count < 1)
        {
          #region Rev Doc
          // collect the unused paths HERE and do the Yes/No-remove
          // later after this loop. The "true" in the call to the engine
          // (above View2Ass) skips that in there now. v4.7.3.72 -JpE-
          #endregion Rev Doc
          none.Add(dir);
          continue;
        }
        list.Add(dict);
      }
      if (list.Count > 0) DisplayResults(list);
      if (none.Count > 0) BatchRemove(none);
    }
 
    private void BatchRemove(ICollection<string> unused)
    {
      #region was
      //foreach (var path in unused)
      //{
      //  if (OPS.Default.reportsListBoxItems.IndexOf(path) < 1) continue;
      //  var text = ORS.OMA_ViewAss + "\n\nPath:\n" + path;
      //  if (MessageBox.Show(text, ORS.OMA_ViewAssTitle,
      //    MessageBoxButtons.YesNo, MessageBoxIcon.Question,
      //    MessageBoxDefaultButton.Button2)
      //      != DialogResult.Yes) continue;
      //  if (path.Equals(OPS.Default.PrefReportsDir))
      //  {
      //    var target =
      //      OPS.Default.reportsListBoxItems.IndexOf(path) + 1;
      //    // if Pref Adopt next in List automatically as new Pref.
      //    if (target == unused.Count) target = 0;
      //    ReportsTextBox.Text = WhatWasItB2 =
      //      OPS.Default.PrefReportsDir =
      //        OPS.Default.reportsListBoxItems[target];
      //    if (target < 1) continue;
      //  }
      //  OPS.Default.reportsListBoxItems.Remove(path);
      //}
      #endregion was
      foreach
        (var path in from path in unused
          where OPS.Default.reportsListBoxItems.IndexOf(path) >= 1
          let text = ORS.OMA_ViewAss + "\n\nPath:\n" + path
          where AST.YesNoDialog(text, ORS.OMA_ViewAssTitle)
          || OPS.Default.MiniVerb
          //|| OPS.Default.AreYouSure
          select path)
      {
        if (path.Equals(OPS.Default.PrefReportsDir))
        {
          var target =
            OPS.Default.reportsListBoxItems.IndexOf(path) + 1;
          // if Pref Adopt next in List automatically as new Pref.
          if (target == unused.Count) target = 0;
          ReportsTextBox.Text = WhatWasItB2 =
            OPS.Default.PrefReportsDir =
            OPS.Default.reportsListBoxItems[target];
          if (target < 1) continue;
        }
        OPS.Default.reportsListBoxItems.Remove(path);
      }
      PopulateListBoxes();
    }
 
    /// <summary> ContextMenuStrip2 Item for Reports Dirs. This one was funner,
    /// it will flip through the data folder list and get the prefs info for 
    /// Reports Folder and Collate a list of those that use the Selected Reports Folder
    /// and the pref filename for each. plagarized from myself in this reWrite for
    /// Collections.Generic.Dictionary: v4.6.9.94 Apr 06 2017 -JpE-
    /// Split into this and the Engine below for ViewAll mods v4.7.3.73 May 15 2017
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void View2AssociationsToolStrip2MenuItemClick(object sender, EventArgs e)
    {
      var dir = reportsListBox.SelectedItem.ToString();
      var dic = new Dictionary<string, string>();
        View2AssociationsEngine(dir, ref dic, false); // !all = single path
      if (dic.Count > 0) DisplayResults(dic);
    }
 
    /// <summary> Split from the above for ReUse with ViewAllAss Mods v4.7.3.74
    /// NOTE that if all == true then it cuts short at the comment defering removals.
    /// Hand crafted to work with ViewAllAssociationsClick(); -JpE- May 17 2017
    /// </summary>
    /// <param name="selected"></param>
    /// <param name="dirFileNameList"></param>
    /// <param name="all"></param>
    private void View2AssociationsEngine
      (string selected, ref Dictionary<string, string> dirFileNameList, bool all)
    {
      var invalid = new Collection<string>();
      var nth = 0;
      try
      {
        foreach (var dataPath in OPS.Default.dataListBoxItems)
        {
          if (!Directory.Exists(dataPath)) { invalid.Add(dataPath); continue; }
          if (!selected.Equals(GetStoredReportsDirPref(dataPath)))  continue;
          // else it found one...
          var key = string.Format("{0}) ", ++nth) + dataPath;
          var prefsFilesName = GetPrefFileName(dataPath);
          if (string.IsNullOrEmpty(prefsFilesName))
          { prefsFilesName = "None Associated"; }
          dirFileNameList.Add(key, prefsFilesName);
        }
      } // <-= End of Loop.
      catch (ArgumentException exception)
      {
        if (IF.Testing)
          MessageBox.Show(exception.ToString()); return;
      }
      if (invalid.Count > 0) RemoveInvalidFolders(true, invalid); // Apt identifiers.
      //   v reworked to do a BatchRemove call in ViewAllAss v72...
      if (all || dirFileNameList.Count > 0) return;
      //   ^ ...& defer removes when "all" arg is true.
      // ViewALL returns here skipping the rest each iteration. So...
      //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
      #region View2 call only sees the rest of this.
      if (!AST.YesNoDialog(ORS.OMA_ViewAss, ORS.OMA_ViewAssTitle)) return;
 
      if (OPS.Default.reportsListBoxItems.IndexOf(selected) < 1)
      { MessageBox.Show(ORS.OF_Remove); return; }
      if (selected.Equals(OPS.Default.PrefReportsDir))
      {
        var target = OPS.Default
          .reportsListBoxItems.IndexOf(selected) + 1;
        if (target == OPS.Default.reportsListBoxItems.Count)
          target = 0;
        // if Pref, Adopt next in List automatically as new Pref.
        ReportsTextBox.Text = WhatWasItB2 =
          OPS.Default.PrefReportsDir =
          OPS.Default.reportsListBoxItems[target];
        if (target == 0) return;
      }
      // either way, it's history...
      OPS.Default.reportsListBoxItems.Remove(selected);
      PopulateListBoxes();
      #endregion View2 call only section.
    }
 
    // v4.7.3.70 May 14 2017
    // Took these to a ShowMe calling DisplayResults()
    private void ViewBackupDataList(object sender, EventArgs e)
    {
      var flag = false;
      var text = "There is no Backup for this List.";
      if (PMS.Default.Bac_dataCollection != null
        && PMS.Default.Bac_dataCollection.Count > 0)
      {
        flag = true;
        text =
          PMS.Default.Bac_dataCollection.Cast<string>()
            .Aggregate("Data Collection:\n\n",
              (current, dir) => current + (dir + "\n"));
      }
      if (!flag) { MessageBox.Show(text); return; }
 
      const string title = "Backup Data Folder List";
      var size = AUS.Default.OMA_D2_Size;
      var loca = AUS.Default.OMA_D2_Loca;
        DisplayResults(text, title, ref size, ref loca);
      AUS.Default.OMA_D2_Size = size;
      AUS.Default.OMA_D2_Loca = loca;
      AUS.Default.Save();
    }
 
    private void ViewBackupReportsList(object sender, EventArgs e)
    {
      var flag = false;
      var text = "There is no Backup for this List.";
      if (PMS.Default.Bac_reportsCollection != null
        && PMS.Default.Bac_reportsCollection.Count > 0)
      {
        flag = true;
        text =
          PMS.Default.Bac_reportsCollection.Cast<string>()
            .Aggregate("Reports Collection:\n\n",
              (current, dir) => current + (dir + "\n"));
      }
      if (!flag) { MessageBox.Show(text); return; }
 
      const string title = "Backup Reports Folder List";
      var size = AUS.Default.OMA_D3_Size;
      var loca = AUS.Default.OMA_D3_Loca;
        DisplayResults(text, title, ref size, ref loca);
      AUS.Default.OMA_D3_Size = size;
      AUS.Default.OMA_D3_Loca = loca;
      AUS.Default.Save();
    }
#endregion Upgrade 4.7.3.73 Updates to existing and new.
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region v4.7.5.25 14Jun17 -=[ THE BIG 2 ]=-
 
    /* Upgrade Adds The Context Menu Items to Backup & Restore
     * The Lists Which are already Saved in PrintMasterSettings.
     * The Save and Restore of Lists is already in & tested. -JpE-
     * Retain/Revert/Cancel is in and tested. The Big 2 methods here
     * are the EventHandlers for these Context Menu Options in each ListBox.
     * They are known here, affectionately, as the Big 2. Each Full Featured.
     * 
     * The rest of the NEXT #region is the various ReUsable Methods that support
     * the Big 2. I wanted to make everything modular and these support methods are
     * very flexible and get used by all 4 of the EventHandlers. Each support method
     * has at least 2 code paths (data true or false) and most have 4 for each occasion.
     * BackupDataList, BackupReportsList, RestoreDataList & RestoreReportsList.
     * I was practicing making things compact and reusable and reducing total code.
     * Updated v4.7.5.28 Jun 16 2017 for the AutoBackup and everything called from
     * AppCode2.Restore4(); for Maintenance.
     * 
     */
 
#region Backup & Backup Specific
 
    /// <summary> BackupDataList Context Menu EventHandler
    /// Split out & consolidated to BackupLists which
    /// now does both. v4.7.5.21 12Jun17
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void BackupDataList(object sender, EventArgs e)
    {
      const bool
        data = true,
        auto = false;
      BackupLists(data, auto);
    }
 
    /// <summary> AutoMode Tricks. v4.7.5.15 10Jun17
    /// v4.7.5.12.3 Jun 08 17 Mods adds BackupListsAuto();
    /// to Restore3, Scheduler Call. Setting sender here
    /// makes it auto-mode there.
    /// So... sig is (bool data, bool auto)
    /// v4.7.5.19 Perfected and Final Testing. 12Jun17
    /// Constructor in OF makes this possible though
    /// it is not static, through an instantiation.
    /// </summary>
    public void BackupListsAuto()
    {
    //BackupLists( data, auto); // por exemplar
      BackupLists( true, true); // datafolders
      BackupLists(false, true); // reportsfolders
    }
 
    /// <summary> BackupReportsList Context Menu EventHandler
    /// Split out & consolidated to BackupLists which
    /// now does both. v4.7.5.21 12Jun17
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void BackupReportsList(object sender, EventArgs e)
    {
      const bool
        data = false,
        auto = false;
      BackupLists(data, auto);
    }
 
    /// <summary> All-In-One Backup Module
    /// RetroFit for automode v4.7.5.23
    /// 12-Jun-2017
    /// </summary>
    /// <param name="data"></param>
    /// <param name="auto"></param>
    private void BackupLists(bool data, bool auto)
    {
      if (!AskUser(data, auto)) return;
      const bool backup = true;
      var merge = false;
      StringCollection unique;
      if (HasUniquePath(data, out unique, backup))
      { // Backup has something unique.
        if (auto) merge = true;
        else
          merge = OPS.Default.MiniVerb
            || AST.YesNoDialog(ORS.OMA_B1, 1);
      }
      var what = 0;
      var both = BothHaveBoth(ref what, data);
      if (!merge && unique.Count > 0)
      {
        var r = AST.YesNoCancel(ORS.OMA_B2, 1);
        if (r == 3) return; // Cancel Clicked.
        if (r == 1)
        {
          DontMerge(data);
          what = 1;
          both = false;
          unique.Clear();
        }
        if (r == 2) merge = true;
      }
      var rr = 0;
      if (!auto)
        if (both && merge)
          rr = RetainRevert(ORS.OMA_B3);
      if (rr > 2) return;
      var retain = rr < 2;
      if (!both)
      {
        if (what  < 2) retain = true;
        if (what == 2) retain = false;
      }
      // what == 1 (is) only in OS, 2 only in PMS, 0 == Neither.
      if (what < 1 && !auto)
      {
        if (data) SoWhat(); // and here
        else SoWhatElse();
      }
      Merger(retain, unique, backup, data, auto); // replace 2nd true for data var inside.
      OPS.Default.Save();
      PMS.Default.Save();
      if (OPS.Default.MiniVerb || auto) return;
      ShowBackupResult(true, merge, retain);
    }
 
    /// <summary> Ask for for User Input to Proceed.
    /// but there is no more Big Four it's the Big two now LoL
    /// The Big two each ate one of the Big 4 but didn't grow.
    /// </summary>
    /// <param name="data"></param>
    /// <param name="auto"></param>
    /// <returns></returns>
    private static bool AskUser(bool data, bool auto)
    {
      // Split out from BackupLists v4.7.5.21
      if (data)
      {
        if (OPS.Default.dataListBoxItems.Count < 1)
        {
          if (!auto) MessageBox.Show(ORS.OMA_E2);
          return false;
        }
        if (!OPS.Default.MiniVerb
          && !OPS.Default.AreYouSure
          && !auto)
            if (!AST.YesNoDialog(ORS.OMA_BDL))
              return false;
      }
      else // if not data it is reports calling.
      {
        if (OPS.Default.reportsListBoxItems.Count < 1)
        {
          if (!auto) MessageBox.Show(ORS.OMA_E3);
          return false;
        }
        if (!OPS.Default.MiniVerb
          && !OPS.Default.AreYouSure && !auto)
          if (!AST.YesNoDialog(ORS.OMA_BRL))
            return false; // Skips in AutoMode.
      }
      return true;
    }
 
    /// <summary> Straight Backup No Merge.
    /// Split out from BackupLists v4.7.5.24
    /// June 13 2017
    /// </summary>
    /// <param name="data"></param>
    private static void DontMerge(bool data)
    {
      if (data)
      {
        PMS.Default.Bac_PrefRootDir  =
          OPS.Default.PrefRootDir;
        PMS.Default.Bac_PrefFileName =
          OPS.Default.PrefFileName;
      }
      else
      {
        PMS.Default.ReportsFolder =
          OPS.Default.PrefReportsDir;
      }
      PMS.Default.Save();
    }
 
    /// <summary> Display results of Backup
    /// Works for either List retrofit and
    /// Split out v4.7.5.24 June 13 2017
    /// </summary>
    /// <param name="data"></param>
    /// <param name="merge"></param>
    /// <param name="retain"></param>
    private static void
      ShowBackupResult(bool data, bool merge, bool retain)
    {
      // Skip-All Setting & AutoMode skip Display Msg.
      var text = ORS.OMA_DLB; // only this var varies.
      if (!data) text = ORS.OMA_RLB;
      if (merge)
      {
        text = retain
          // True/False, Left to Right as assignment.
          ? ORS.OMA_B4 : ORS.OMA_B5;
        text += "\n\n" + ORS.OMA_B6;
      }
      MessageBox.Show(text);
    }
#endregion Backup & Backup Specific
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
#region Restore & Restore Specific
 
    /* Early Analysis and Design Notes:
     * 
     * 1) Which methods from DataList are reUseable?
     *  a) Houston()
     *  b) Obviously, YesNoDialog() LoL
     *  c) HasUniquePath(false, out unique) is it. (false is Reports)
     *  d) RetainRevert & the RetainRevertCancel Object are very reUsable.
     *  e) AddUnique() is reUsable with false for reports.
     *  f) A Reports-Folder-Select thingy exists somewhere in this source code file.
     *  
     * 2) Which are not, AND which will be needed? (ie. rewritten for Reports.)
     *  a) BothHaveBoth can be BothHaveIt() for reports List.
     *  b) Merger(), RevertPrefs and MergeLists() will all have to be at-least
     *  edited for ReportsList. Maybe modified to do both or cloned out to it's own method.
     *  c) A desperate call to SoWhat() may be needed. The else branch of
     *  the DataList version seems reUsable enough maybe?
     *  d) SelectRootDir() can be cloned and edited easily enough.
     *  
     * 3) Which are not, but will not be needed?
     *  b) I'm not sure ReCheck() in any form will be needed. Maybe something else?
     *  
     * 4) What methods will be completely new in ReportsList?
     *  a) All of them LOL, they evolved to be 4 function each for backups and restores
     *  b) and for data and reports. Most go all four ways LoL. v4.7.3.65 May 11 2017
     *  By:
     *   John.P.Edwards dba Global Access Software Intl.
     *   Designed, Produced, Coded, Tested and Developed by -JpE- (C) 2011-2026
     */
 
    private void RestoreDataList(object sender, EventArgs e)
    {
      const bool data = true;
      RestoreLists(data);
    }
 
    private void RestoreReportsList(object sender, EventArgs e)
    {
      const bool data = false;
      RestoreLists(data);
    }
 
    private void RestoreLists(bool data)
    {
      // Store & Retrieve PrefRoot, Reports and FileName as well.
      // Retain members of this list that do not appear in the backup?
      if (!AskUser2(data)) return;
      const bool backup = false, auto = false;
      var merge = false;
      StringCollection unique;
      if (HasUniquePath(data, out unique, backup))
        merge = OPS.Default.MiniVerb 
          || AST.YesNoDialog(ORS.OMA_R1, 1);
      var what = 0;
      var both = BothHaveBoth(ref what, data);
      // if (!both && which == 1 = only in OS, 2 = only in PMS,
      // 0 = Neither has needed Info.
      if (!merge && unique.Count > 0)
      {
        //  v added v4.7.2.55 May 05
        var r = AST.YesNoCancel(ORS.OMA_R2, 1);
        if (r == 3) return;
        if (r == 1)
        {
          DontMerge2(data);
          what = 2;
          both = false;
          unique.Clear();
        }
        if (r == 2) merge = true;
      }
      var rr = 0; // Retain the Preferred Folders
      // ...and FileName or revert to backup?
      if (both && merge) rr = RetainRevert();
      // ^ returns 1 if retain & 2 if revert, 3 if Cancel.
      if (rr > 2) return; // Cancel.
      // Which leaves only 0, 1 & 2 on the table.
      var retain = rr < 2;// == 1;
      //  retain = true is retain, false is revert. 
      if (!both)
      {
        if (what  < 2) retain = true;
        if (what == 2) retain = false;
      }
      if (what.Equals(0))
      {
        if (data) SoWhat();
        else SoWhatElse();
      }
      // All set, let's do it!
      Merger(retain, unique, backup, data, auto);
      Changes(data);
      // And now that it is restored...
      if (OPS.Default.MiniVerb) return;
      ShowRestoreResult(data, merge, retain);
    }
 
    private void Changes(bool data)
    {
      if (data)
      {
        folderBrowser.SelectedPath =
          OPS.Default.PrefRootDir;
        DataChanges();
      }
      else
      {
        folderBrowser.SelectedPath =
          OPS.Default.PrefReportsDir;
        ReportsChanges();
      }
    }
 
    private static void DontMerge2(bool data)
    {
      if (data)
      {
        OPS.Default.PrefFileName = PMS.Default.Bac_PrefFileName;
        OPS.Default.PrefRootDir = PMS.Default.Bac_PrefRootDir;
        OPS.Default.PrefReportsDir = PMS.Default.ReportsFolder;
      }
      else
        OPS.Default.PrefReportsDir = PMS.Default.ReportsFolder;
    }
 
    private static bool AskUser2(bool data)
    {
      if (Houston())
      { // aka We have a problem!
        MessageBox.Show(ORS.OMA_E1);
        return false;
      }
      var msg = ORS.OMA_RDL;
      if (!data) msg = ORS.OMA_RRL;
      if ( !OPS.Default.MiniVerb
        && !OPS.Default.AreYouSure)
          if (!AST.YesNoDialog(msg)) return false;
      return true;
    }
 
    private static void ShowRestoreResult
      (bool data, bool merge, bool retain)
    {
      var text = ORS.OMA_DLR;
      if (!data) text = ORS.OMA_RLR;
      if (merge)
      {
        text  = retain ? ORS.OMA_R3 : ORS.OMA_R4;
        text += "\n\n" + ORS.OMA_R5;
      }
      MessageBox.Show(text);
    }
 
#endregion Restore & Restore Specific
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
    
#endregion v4.7.2.56-65 May 06-11 2017 -=[ THE BIG 2 ]=-
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Supporting Methods FOR 4 way w/ -=[ THE BIG 2 ]=-
 
    // NOTE: retain == true to retain, false to revert.
    // what == 1 means only in OS, 2 means only in PMS,
    // (retain defaults to true if what==1, false if what==2)
    // both == true means Both Have BOTH PrefRootDir & PrefFileName.
 
    /// <summary> Quad Function Router for the Big 2 Method Groups:
    /// BackupDataList, RestoreDataList, BackupReports & RestoreReports.
    /// Retain and Revert Logic Switched up on Backups and Worded differently
    /// in the RetainRevert() call. Feature adds full functionality for Lists.
    /// 4 code paths for backup and data, true or false as illustrated.
    /// backup true - data true, backup true - data false, backup false - data true,
    /// and backup false - data false. Are all covered here for the Big 4 Methods.
    /// And further switched herein by retain. For 8 possible code paths in one here.
    /// auto is only true if this is an Automatic-Backup of either List.
    /// v4.7.5.25 Compatible, nothing changed down here, just in the Big 2 above.
    /// </summary>
    /// <param name="retain"></param>
    /// <param name="unique"></param>
    /// <param name="backup"></param>
    /// <param name="data"></param>
    /// <param name="auto"></param>
    private void Merger(
      bool retain, StringCollection unique,
      bool backup, bool data, bool auto)
    {
      if (!backup) { if (!retain) RevertPrefs(data); }
      // if retain we're already set.
      else
      { // backup == true
        if (retain)
        {
          if (data)
          { // DataList, Backup, Retain.
            PMS.Default.Bac_PrefRootDir  = OPS.Default.PrefRootDir;
            PMS.Default.Bac_PrefFileName = OPS.Default.PrefFileName;
          }
          else PMS.Default.ReportsFolder = OPS.Default.PrefReportsDir; // Rprts.
        }
        else
        { // if (!retain && backup) Revert Backup to Backup Prefs.
          var c = unique.Count;
          if (data)
          { // Data List, Backup, Revert. (True/False v)
            var dir = c > 0 ? unique[0] : PMS.Default.Bac_PrefRootDir;
            if (Directory.Exists(dir)) PMS.Default.Bac_PrefRootDir = dir;
            else if (!auto) SoWhat();
            var fn  = GetPrefFileName(dir);
            if (File.Exists(dir + "\\" + fn))
              PMS.Default.Bac_PrefFileName = fn;
            else if (!auto) SoWhat();
          }
          else
          { // Reports List Backup, Revert.
            var dir = c > 0 ? unique[0] : PMS.Default.ReportsFolder;
            if (Directory.Exists(dir)) PMS.Default.ReportsFolder = dir;
            else if (!auto) SoWhatElse();
          }
        } // Then just flip it on Backups, for best affect. ;-)
        retain = !retain;
      }
      // Now Merge them according to retain, backup & data.
      if (data) MergeDataLists(retain, unique, backup);
      else   MergeReportsLists(retain, unique, backup);
      // ^ Data/Reports Differs here+Backup/Restore ^ differs there.
    }
 
    /// <summary> Runs only from the 2 Restore Tasks.
    /// Reverts the Current Prefs to the Backup Prefs.
    /// data == true is Data LIst, false is Reports.
    /// </summary>
    /// <param name="data"></param>
    private void RevertPrefs(bool data)
    {
      if (data)
      {
        // Use Prefs from PMS.
        var dir = DataTextBox.Text = WhatWasItB4 =
          OPS.Default.PrefRootDir  = PMS.Default.Bac_PrefRootDir;
        var fnp = GetPrefFileName(dir);
        var rec = GetStoredReportsDirPref(dir);
        var tea = false;
        if (!File.Exists(dir + "\\" + fnp)) { SoWhat(); tea = true; }
        if (!Directory.Exists(rec)) { SoWhatElse(); tea = true; }
        if (tea) return;// tea time, bye!
        // ^^^^ I bet flow never gets to either, but Justin Case.
        OPS.Default.PrefFileName = fnp;
        ReportsTextBox.Text = OPS.Default.PrefReportsDir = rec;
      }
      else
      {
        var or = OPS.Default.PrefReportsDir;
        var pr = PMS.Default.ReportsFolder;
        if (Directory.Exists(pr)) ReportsTextBox.Text =
          OPS.Default.PrefReportsDir = WhatWasItB2 = pr;
        else
        {
          if (Directory.Exists(or)) return;
            SoWhatElse();
          if (Directory.Exists(OPS.Default.PrefReportsDir)) return;
          var ok = ReportsTextBox.Text = OPS.Default.PrefReportsDir =
            OPS.Default.PrefRootDir + "\\" +
              PMS.Default.Reports;
          if (!Directory.Exists(ok))
            Directory.CreateDirectory(ok);
        }
      }
    }
 
    /// <summary> if backup == false then it's a Restore Task.
    /// If Revert, it tacks the diffs on the end, (retain==false)
    /// if Retain, it puts them up top. NOTE: Reversed for Backups!
    /// if backup == true then it's a little different logic circuit:
    /// Retain puts the diffs from backup at the bottom, keeping the Current.
    /// Revert puts the diffs from backup at the Top of the List.
    /// Merges the two Data Folder Lists.
    /// </summary>
    /// <param name="retain"></param>
    /// <param name="unique"></param>
    /// <param name="backup"></param>
    private static void MergeDataLists
      (bool retain, IEnumerable unique, bool backup)
    {
      if (backup) // We're backing up the Current List.
      {
        if (PMS.Default.Bac_dataCollection == null)
          PMS.Default.Bac_dataCollection = new StringCollection();
        var _default = OPS.Default.dataListBoxItems[0];
        PMS.Default.Bac_dataCollection.Clear();
        PMS.Default.Bac_dataCollection.Add(_default);
        var enumerable = unique as object[]
          ?? unique.Cast<object>().ToArray();
        if (retain) AddUnique(true, enumerable, true);
        foreach (var dir in OPS.Default
          .dataListBoxItems.Cast<string>()
          .Where(Directory.Exists)
          .Where(dir => !dir.Equals(_default)))
            PMS.Default.Bac_dataCollection.Add(dir);
        if (!retain) AddUnique(true, enumerable, true);
      }
      else // It's a Restore Task.
      {
        // Either way, We will clear and refill the List.
        // But grab the default and keep it up Top always.
        if (PMS.Default.Bac_dataCollection == null)
          PMS.Default.Bac_dataCollection = new StringCollection();
        var _default = OPS.Default.dataListBoxItems[0];
        OPS.Default.dataListBoxItems.Clear();
        OPS.Default.dataListBoxItems.Add(_default);
        // if Retain, Put the diffs up Top.
        var enumerable = unique as object[]
          ?? unique.Cast<object>().ToArray();
        if (retain) AddUnique(true, enumerable, false);
        foreach (var dir in PMS.Default
          .Bac_dataCollection.Cast<string>()
          .Where(Directory.Exists)
          .Where(dir => !dir.Equals(_default)))
            OPS.Default.dataListBoxItems.Add(dir);
        // Else, Tack diffs on the end.
        if (!retain) AddUnique(true, enumerable, false);
      }
    }
 
    /// <summary> if backup == false then it's a Restore Task.
    /// If Revert, it tacks the diffs on the end, (retain==false)
    /// if Retain, it puts them up top. NOTE: Reversed for Backups!
    /// if backup == true then it's a little different logic circuit:
    /// Retain puts the diffs from backup at the bottom, keeping the Current.
    /// Revert puts the diffs from backup at the Top of the List.
    /// Merges the two Reports Folder Lists.
    /// </summary>
    /// <param name="retain"></param>
    /// <param name="unique"></param>
    /// <param name="backup"></param>
    private static void MergeReportsLists
      (bool retain, IEnumerable unique, bool backup)
    {
      if (backup) // it's a Backup Task.
      {
        if (PMS.Default.Bac_reportsCollection.Equals(null))
          PMS.Default.Bac_reportsCollection = new StringCollection();
        var d = OPS.Default.reportsListBoxItems[0];
        PMS.Default.Bac_reportsCollection.Clear();
        PMS.Default.Bac_reportsCollection.Add(d);
        var e = unique as object[]
          ?? unique.Cast<object>().ToArray();
        if (retain) AddUnique(false, e, true);
        foreach (var dir in OPS.Default
          .reportsListBoxItems.Cast<string>()
          .Where(Directory.Exists)
          .Where(dir => !dir.Equals(d)))
            PMS.Default.Bac_reportsCollection.Add(dir);
        if (!retain) AddUnique(false, e, true);
      }
      else // it's a restore task. (already tested below)
      {
        if (PMS.Default.Bac_reportsCollection.Equals(null))
          PMS.Default.Bac_reportsCollection = new StringCollection();
        var d = OPS.Default.reportsListBoxItems[0];
        OPS.Default.reportsListBoxItems.Clear();
        OPS.Default.reportsListBoxItems.Add(d);
        var e = unique as object[]
          ?? unique.Cast<object>().ToArray();
        if (retain) AddUnique(false, e, false);
        foreach (var dir in PMS.Default
          .Bac_reportsCollection.Cast<string>()
          .Where(Directory.Exists)
          .Where(dir => !dir.Equals(d)))
            OPS.Default.reportsListBoxItems.Add(dir);
        if (!retain) AddUnique(false, e, false);
      }
    }
 
    /// <summary> Adds the unique paths to the appropriate collection:
    /// if data == true then it's Data Folders, if false it's Reports.
    /// if backup == true it's a backup Task, if false it's a Restore Task.
    /// NOTE: The if (backup) lines and their else makes it quad function.
    /// </summary>
    /// <param name="data"></param>
    /// <param name="unique"></param>
    /// <param name="backup"></param>
    private static void AddUnique
      (bool data, IEnumerable unique, bool backup)
    {
      if (data) // Data List.
      {
        foreach (var dir in unique.Cast<string>()
          .Where(dir => Directory.Exists(dir)
            && HasDataFiles(dir)))
        {
          // if added to make universal v4.7.2.58
          if (backup) PMS.Default.Bac_dataCollection.Add(dir);
          else OPS.Default.dataListBoxItems.Add(dir);
        }
      }
      else // Reports List.
      {
        foreach (var dir in unique.Cast<string>()
          .Where(Directory.Exists))
        {
          // if added to make universal v4.7.2.58
          if (backup) PMS.Default.Bac_reportsCollection.Add(dir);
          else OPS.Default.reportsListBoxItems.Add(dir);
        }
      }
    }
 
    /// <summary> 1 = only in OS, 2 = only in PMS, 0 = Neither.
    /// What's up with what: True = Yes, Both. what = 0; in call btw.
    /// Just Check; that current and backup collections both have;
    /// both PrefFileName and PrefRootDir. (BothHaveBoth!)
    /// For Reports (data==false); it Checks if Both Have IT.
    /// (PrefReportsDir) Same Logic. And Same for Backup & Restore.
    /// So that doesn't matter here. All 4 of the Big 4 call this method.
    /// It's results are just interpreted differently during a Backup
    /// back in the calling methods. No differentiation here for that.
    /// </summary>
    /// <param name="what"></param>
    /// <param name="data"></param>
    /// <returns></returns>
    private bool BothHaveBoth(ref int what, bool data)
    {
      var result = false;
      if (!data)
      {
        var or = OPS.Default.PrefReportsDir;
        var pr = PMS.Default.ReportsFolder;
        var ol = OPS.Default.reportsListBoxItems;
        var pl = PMS.Default.Bac_reportsCollection;
 
        if (Directory.Exists(or) && ol.Contains(or)) what = 1;
        if (Directory.Exists(pr) && pl.Contains(pr))
        {
          if (what == 1) result = true;
          what = 2;
        }
        return result;
      } // else it is Data...
      var osF = OPS.Default.PrefFileName;
      var osR = OPS.Default.PrefRootDir;
      var psF = PMS.Default.Bac_PrefFileName;
      var psR = PMS.Default.Bac_PrefRootDir;
      if (Directory.Exists(osR))
      { if (File.Exists(osR + "\\" + osF)) what = 1;}
      if (Directory.Exists(psR))
      {
        if (File.Exists(psR + "\\" + psF))
        {
          if (what.Equals(1)) result = true;
          what = 2;
        }
      } // If one does not, try to use the pref.lbs before final assessment.
      if (what == 1) // (2) pms does not. Backup does not. False.
      { if (ReCheck(false)) result = true; }
      if (what == 2 && result.Equals(false)) // (1) os does not. True.
      // Fat chance but I'll cover it anyway. LoL.
      { if (ReCheck(true))  result = true; }
      return result;
    }
 
    // os false is re check pms,
    // os true  is re check os. Hello!!!
    // (not likely, but covered anyway.)
    private bool ReCheck(bool ops)
    {
      var found1 = false;
      if (ops) found1 = ReCheckOps();
      else
      { // pms
        var list = PMS.Default.Bac_dataCollection;
        int count = list.Count,
            index = 1;
        if (count < 1) return false;
        for (; index < count; ++index)
        {
          var dir = list[index];
          var filename = FileName;
          FileName = "";
          var file = GetPrefFileName(dir);
          FileName = filename;
          var path = PMS.Default.ReportsFolder;
          PMS.Default.ReportsFolder = "";
          var repo = GetStoredReportsDirPref(dir);
          PMS.Default.ReportsFolder = path;
          if (!Directory.Exists(dir) || !HasDataFiles(dir)
            || !File.Exists(dir + "\\" + file)
            || string.IsNullOrEmpty(file)
            || string.IsNullOrEmpty(repo)) continue;
 
          PMS.Default.Bac_PrefFileName  = file;
          PMS.Default.Bac_PrefRootDir   = dir;
          found1 = true;
          if (Directory.Exists(repo))
            PMS.Default.ReportsFolder   = repo;
          else
          {
            var test = OPS.Default.PrefReportsDir;
            if (Directory.Exists(test))
            {
              PMS.Default.ReportsFolder = test;
            }
            else
            {
              test = AUS.Default.RootDir;
              if (Directory.Exists(test))
                PMS.Default.ReportsFolder = test;
              else
              {
                var check = AUS.Default.AppDir +
                  "\\" + APS.Default.Home +
                  "\\" + PMS.Default.Reports;
                if (Directory.Exists(check))
                  PMS.Default.ReportsFolder = check;
                else found1 = false;
              }
            }
          }
          break;
        } // end of For Loop.
      }
      return found1;
    }
 
    private bool ReCheckOps()
    {
      var found = false;
      var list  = OPS.Default.dataListBoxItems;
      var count = list.Count;
      if (count < 1) return false;
      var index = 1;
      for (;index < count; ++index)
      {
        var dir  = list[index];
        var filename = FileName;
        FileName = "";
        var file = GetPrefFileName(dir);
        FileName = filename;
        var path = OPS.Default.PrefReportsDir;
        OPS.Default.PrefReportsDir = "";
        var repo = GetStoredReportsDirPref(dir);
        OPS.Default.PrefReportsDir = path;
        if (!Directory.Exists(dir) || !HasDataFiles(dir)
          || !File.Exists(dir + "\\" + file)
          || string.IsNullOrEmpty(file)
          || string.IsNullOrEmpty(repo)) continue;
 
        OPS.Default.PrefFileName = file;
        OPS.Default.PrefRootDir = dir;
        found = true;
        if (Directory.Exists(repo))
          OPS.Default.PrefReportsDir = repo;
        else
        {
          var test = OPS.Default.PrefReportsDir;
          if (Directory.Exists(test))
            OPS.Default.PrefReportsDir = test;
          else
          {
            test = AUS.Default.RootDir;
            if (Directory.Exists(test))
              OPS.Default.PrefReportsDir = test;
            else
            {
              var check =
                AUS.Default.AppDir +
                "\\" + APS.Default.Home +
                "\\" + PMS.Default.Reports;
              if (Directory.Exists(check))
                OPS.Default.PrefReportsDir = check;
              else found = false;
            }
          }
        }
        break;
      } // end of For Loop.
      return found;
    }
 
    private void SoWhat()
    {
      var x = OPS.Default.dataListBoxItems.Count < 2 ? 0 : 1;
      var d = OPS.Default.PrefRootDir = OPS.Default.dataListBoxItems[x];
      // this ^ one has already been tested for Dir.Exists and HasDataFiles.
      if (string.IsNullOrEmpty(d) // All 3 If Needed <-= v
        || !Directory.Exists(d)) d = SelectRootDir(); // <-= TestsWell!
      var f = GetPrefFileName(d);
      var r = GetStoredReportsDirPref(d);
      var t = false;
      if (File.Exists(d + "\\" + f))
      {
        t = true; // true testswell, false too.
        OPS.Default.PrefFileName = f;
      }
      if (!t)
      {
        var size = AUS.Default.OMA_FileSelect_Size;
        var location = AUS.Default.OMA_FileSelect_Location;
        var list = GetDataFileList(d);
 
        // v4.7.3.93 index mods
        var index = 0;
        var test = GetPrefFileName(OPS.Default.PrefRootDir);
        if (list.Contains(test))
          index = list.IndexOf(test);
        else
          if (list.Contains(OPS.Default.PrefFileName))
            index = list.IndexOf(OPS.Default.PrefFileName);
          else
            if (list.Contains(PMS.Default.Bac_PrefFileName))
              index = list.IndexOf(PMS.Default.Bac_PrefFileName);
            else
              if (list.Contains(AUS.Default.FileName))
                index = list.IndexOf(AUS.Default.FileName);
              else
                if (list.Contains(APS.Default.defaultFilename))
                  index = list.IndexOf(APS.Default.defaultFilename);
                // else default to the index[0] default.
        // ^ v4.7.3.93 May 30 2017
        var choice = SelectOne(list, ref size, ref location, "", index); // <-=/\/\/\/\/\
        AUS.Default.OMA_FileSelect_Size = size;
        AUS.Default.OMA_FileSelect_Location = location;
        AUS.Default.Save();
        if (string.IsNullOrEmpty(choice)) choice = list[index];
        OPS.Default.PrefFileName = choice;
      }
      if (Directory.Exists(r)) OPS.Default.PrefReportsDir = r;
      else SoWhatElse();
    }
 
    /// <summary> Split out and ReUsed by RestoreReportsList() v4.7.2.51
    /// This was the else portion of SoWhat() btw. LoL
    /// Aptly named therefor.
    /// </summary>
    private void SoWhatElse()
    {
      var list7 = OPS.Default.reportsListBoxItems;
      var list8 = new Collection<string>();
      const string title = "Select a Reports Folder:";
      foreach (var path in list7.Cast<string>()
        .Where(Directory.Exists)) list8.Add(path);
 
      // vvvvvvvvvv v4.7.3.93 May 30 2017
      var index = 0;
      var test  = GetStoredReportsDirPref(OPS.Default.PrefRootDir);
      if (list8.Contains(test)) index = list8.IndexOf(test);
      else
        if (list8.Contains(OPS.Default.PrefReportsDir))
          index = list8.IndexOf(OPS.Default.PrefReportsDir);
        else
          if (list8.Contains(PMS.Default.ReportsFolder))
            index = list8.IndexOf(PMS.Default.ReportsFolder);
          // else default to the index[0] default.
      // ^ v4.7.3.93 May 30 2017
 
      var size   = AUS.Default.OMA_ReportsSelect_Size;
      var locate = AUS.Default.OMA_ReportsSelect_Location;
      var report = SelectOne(list8, ref size, ref locate, title, index); // <-=/\/\/\/\/\
      AUS.Default.OMA_ReportsSelect_Size = size;
      AUS.Default.OMA_ReportsSelect_Location = locate;
      AUS.Default.Save();
      if (string.IsNullOrEmpty(report)) report = list8[index];
      OPS.Default.PrefReportsDir = report;
    }
 
    private string SelectRootDir()
    {
      var d = AUS.Default.AppDir + "\\" + APS.Default.Home;
      var c = OPS.Default.dataListBoxItems.Count;
      if (c == 1) d = OPS.Default.dataListBoxItems[0];
      if (c < 2) return d;
      // So, whereever there are two or more.
      var list = new Collection<string>();
      foreach (var dir in OPS.Default.dataListBoxItems
        .Cast<string>().Where(dir => Directory.Exists(dir)
          && HasDataFiles(dir))) list.Add(dir);
      if (list.Count < 2) return list.Count == 1 ? list[0] : d;
 
      // vvvvvvvvvv v4.7.3.93
      var index = 0;
      var test  = OPS.Default.PrefRootDir;
      if (list.Contains(test))
        index   = list.IndexOf(test);
      else
        if (list.Contains(AUS.Default.RootDir))
          index = list.IndexOf(AUS.Default.RootDir);
        else
          if (list.Contains(PMS.Default.Bac_PrefRootDir))
            index = list.IndexOf(PMS.Default.Bac_PrefRootDir);
          // else default to the index[0] default.
      // ^^^^^ v4.7.3.93 May 30 2017
 
 
      const string title = "Please Select a Data Folder:";
      var s = AUS.Default.OMA_ReportsSelect_Size;
      var l = AUS.Default.OMA_ReportsSelect_Location;
      var a = SelectOne(list, ref s, ref l, title, index); // <<=====<<
      AUS.Default.OMA_ReportsSelect_Location = l;
      AUS.Default.OMA_ReportsSelect_Size = s;
      AUS.Default.Save();
      if (string.IsNullOrEmpty(a)
        || !Directory.Exists(a)) a = list[index];
 
      return a;
    }
 
    /// <summary> See if the Current List has anything Unique,
    /// / Not in the Backup. Adds these to the unique Collection.
    /// bool = true is Data Folders, false is Reports folder lists.
    /// </summary>
    /// <param name="data"></param>
    /// <param name="unique"></param>
    /// <param name="backup"> </param>
    /// <returns></returns>
    private bool HasUniquePath
      (bool data, out StringCollection unique, bool backup)
    {
      CheckPrefs();
        unique  = new StringCollection();
      var list1 = OPS.Default.dataListBoxItems;
      var list2 = PMS.Default.Bac_dataCollection;
 
      if (!data) // Defaults ^ to Data, false for Reports Collection.
      {
        list1 = OPS.Default.reportsListBoxItems;
        list2 = PMS.Default.Bac_reportsCollection;
      }
 
      if (backup) // Then just...
      {
        foreach (var path in from string path in list2
          where !list1.Contains(path)
          where Directory.Exists(path)
            select path) unique.Add(path);
      }
      else // Below Well Tested Restore Mods.
      {
        foreach (var path in from string path in list1
          where !list2.Contains(path)
          where Directory.Exists(path)
            select path) unique.Add(path);
      }
      return unique.Count > 0;
    }
 
    /// <summary> Check for any Problems
    /// with the Collections & PrefFileName, etc.
    /// </summary>
    /// <returns></returns>
    private static bool Houston()
    { // Justin Case it's a WipEd RuN.
      if (PMS.Default.Bac_dataCollection.Equals(null))
        PMS.Default.Bac_dataCollection = new StringCollection();
      if (PMS.Default.Bac_reportsCollection.Equals(null))
        PMS.Default.Bac_reportsCollection = new StringCollection();
 
      return
           PMS.Default.Bac_dataCollection.Count < 1
        || PMS.Default.Bac_reportsCollection.Count < 1
        || string.IsNullOrEmpty(PMS.Default.Bac_PrefFileName)
        || string.IsNullOrEmpty(PMS.Default.Bac_PrefRootDir)
        || string.IsNullOrEmpty(PMS.Default.ReportsFolder);
      // Check for string.nullorempty ^ in which case: show msg.
    }
 
    /// <summary> returns 1 if Retain, 2 if Revert, 3 if Cancel.
    /// Send it the public Properties LabelText, FormLocation,
    /// FormForeColor, FormBackColor. LabelText is Optional as
    /// are the others of course. TestsWell! v4.7.1.38
    /// </summary>
    /// <returns></returns>
    private int RetainRevert()
    {
      const string txt = "";
      return RetainRevert(txt);
    }
    private int RetainRevert(string txt)
    {
      int chosen;
      using (var rrc = new RetainRevertCancel())
      { // ReUsable Custom Class ^ Object Instantiation.
        rrc.LabelText     = txt; // default if empty.
        rrc.FormLocation  = AUS.Default.RRC_Location;
        rrc.FormForeColor = TabForeColor;
        rrc.FormBackColor = TabBackColor;
        rrc.ShowDialog(); // <-=/\/\/\/\/\/\/\/\/\/****
        AUS.Default.RRC_Location = rrc.Location;
        AUS.Default.Save();
        chosen = rrc.ButtonClicked;
      }
      return chosen;
    }
#endregion Supporting Methods for the Big 2 Above.
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#endregion Context Menu Items
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#region Upgrade 4.7.0.07 Apr 13 2017
 
    /// <summary> Checks for a pref.lbs and gets the pref Reports folder from it.
    /// Then AddsToPathCollection(path, false) or whatever.
    /// 
    /// Called only in OptionsFormLoad(); on entry.
    /// </summary>
    private void CheckReportsCollection()
    {
      var invalid = new List<string>();
      var missing = new List<string>();
      foreach (var dataPath in OPS.Default.dataListBoxItems)
      {
        if (!Directory.Exists(dataPath)) { invalid.Add(dataPath); continue; }
        // else...
        var reports = GetStoredReportsDirPref(dataPath);
        if (!OPS.Default.reportsListBoxItems.Contains(reports)
          && Directory.Exists(reports)
          && !missing.Contains(reports)) { missing.Add(reports); }
      }   // Last line here ^ should fix dup reports dirs. v4.7.0.05 Apr 13
      if (missing.Count > 0)
      {
        if (AST.YesNoDialog("Add Missing Reports Folders to the Collection?"))
        {
          var _default = AUS.Default.AppDir + "\\" +
            APS.Default.Home + "\\" + PMS.Default.Reports;
 
          var count = OPS.Default.reportsListBoxItems.Count;
          if (count < 2
            || !OPS.Default.reportsListBoxItems.Contains(_default))
          {
            if (OPS.Default.reportsListBoxItems.Contains(_default)
              && OPS.Default.reportsListBoxItems.IndexOf(_default) > 0)
            {
              OPS.Default.reportsListBoxItems.Remove(_default);
              --count;
            }
            if (!OPS.Default.reportsListBoxItems.Contains(_default))
            {
              if (count.Equals(0)) OPS.Default.reportsListBoxItems.Add(_default);
              else OPS.Default.reportsListBoxItems.Insert(0, _default);
            }
          }
          if (missing.Contains(_default)) missing.Remove(_default);
          foreach (var dir in missing)
          {
            OPS.Default.reportsListBoxItems.Add(dir);
          }
        }
      }
      RemoveInvalidFolders(true, invalid);
    }
 
    /// <summary> Stores everything in OMA Settings Wise on FormLoad.
    /// so it can be brought back on Cancel/Abort/Red-X.
    /// </summary>
    private void SaveInitialSettings()
    {
      CreateNewDetectionStrings();
      // ^ Added v4.7.0.07
      _data.Clear();
      foreach (var str in OPS.Default.dataListBoxItems)
      { _data.Add(str); }
 
      _reports.Clear();
      foreach (var str in OPS.Default.reportsListBoxItems)
      { _reports.Add(str); }
 
      if (!OPS.Default.Schedule1
        || OPS.Default.Scheduled1 < DateTime.Now.AddYears(-1))
      { // wipe bugg fixed ^v v4.7.2.44 Apr 29 2017
        OPS.Default.Schedule1  = true;
        OPS.Default.Scheduled1 = DateTime.Now;
        OPS.Default.Save();
      }
      _scheduler[0] = OPS.Default.Schedule1;
      _scheduler[1] = OPS.Default.Schedule3;
      _scheduler[2] = OPS.Default.Schedule5;
      if (_scheduler[0]) _scheduled[0] = OPS.Default.Scheduled1;
      if (_scheduler[1]) _scheduled[1] = OPS.Default.Scheduled3;
      if (_scheduler[2]) _scheduled[2] = OPS.Default.Scheduled5;
 
      CheckPrefs(); // <-= WipeSchedule Bugg Fixed v4.7.2.44
      // v v4.7.0.07 Scheduler Upgrade Apr 14 2017
      DayOfWeekCheckBox.Checked = DayOfWeek = OPS.Default.DoW;
      Change = false;
    }
 
    private void CreateNewDetectionStrings()
    {
      Data = OPS.Default.dataListBoxItems.Cast<string>()
        .Aggregate((current, str) => current + str);
 
      Reports = OPS.Default.reportsListBoxItems.Cast<string>()
        .Aggregate((current, str) => current + str);
    }
 
    /// <summary> Then comes back here from FormClosing for the Below.
    /// Because of Change == false; above, But only if !ForReal == true;
    /// If (ForReal == true) then nothing needs to be brought back at-all.
    /// </summary>
    private void AbortChanges()
    {
      OPS.Default.dataListBoxItems.Clear();
      foreach (var str in _data)
      { OPS.Default.dataListBoxItems.Add(str); }
 
      OPS.Default.reportsListBoxItems.Clear();
      foreach (var str in _reports)
      { OPS.Default.reportsListBoxItems.Add(str); }
 
      OPS.Default.Schedule1  = _scheduler[0];
      OPS.Default.Schedule3  = _scheduler[1];
      OPS.Default.Schedule5  = _scheduler[2];
 
      OPS.Default.Scheduled1 = _scheduled[0];
      OPS.Default.Scheduled3 = _scheduled[1];
      OPS.Default.Scheduled5 = _scheduled[2];
 
      if (!string.IsNullOrEmpty(PrefFilename))
        OPS.Default.PrefFileName = PrefFilename;
      if (!string.IsNullOrEmpty(PrefRootDir))
        OPS.Default.PrefRootDir  = PrefRootDir;
      if (!string.IsNullOrEmpty(PrefReports))
        OPS.Default.PrefReportsDir = PrefReports;
      OPS.Default.DoW = DayOfWeek;
      OPS.Default.Save();
    }
 
    /// <summary> returns true if anything changed this run.
    /// </summary>
    /// <returns></returns>
    private bool SettingsChanged()
    {
      if (CheckPrefs()) return true;
      bool
        s1 = _scheduler[0],
        s3 = _scheduler[1],
        s5 = _scheduler[2];
      DateTime
        t1 = _scheduled[0],
        t3 = _scheduled[1],
        t5 = _scheduled[2];
      return
           !s1.Equals(OPS.Default.Schedule1)
        || !s3.Equals(OPS.Default.Schedule3)
        || !s5.Equals(OPS.Default.Schedule5)
        ||  s1 && !t1.Equals(OPS.Default.Scheduled1)
        ||  s3 && !t3.Equals(OPS.Default.Scheduled3)
        ||  s5 && !t5.Equals(OPS.Default.Scheduled5)
        ||   CheckCollections()
        || !PrefFilename.Equals(OPS.Default.PrefFileName)
        || !PrefRootDir .Equals(OPS.Default.PrefRootDir)
        || !PrefReports .Equals(OPS.Default.PrefReportsDir)
        || !DayOfWeek   .Equals(OPS.Default.DoW);
    }
 
    // Added v4.7.2.44 Apr 29 2017
    private bool CheckPrefs()
    {
      var result = false;
      if (string.IsNullOrEmpty(PrefFilename))
      {
        result = true;
        var pf = AUS.Default.FileName;
        if (!string.IsNullOrEmpty(pf)
          && File.Exists(AUS.Default.RootDir + "\\" + pf))
          PrefFilename = OPS.Default.PrefFileName = pf;
        else
          PrefFilename = OPS.Default.PrefFileName =
            APS.Default.defaultFilename;
      }
      if (string.IsNullOrEmpty(PrefRootDir))
      {
        result = true;
        var pr = AUS.Default.RootDir;
        if (!string.IsNullOrEmpty(pr)
          && Directory.Exists(pr))
            PrefRootDir = OPS.Default.PrefRootDir = pr;
        else
          PrefRootDir = OPS.Default.PrefRootDir =
            AUS.Default.AppDir + "\\" + APS.Default.Home;
      }
      if (string.IsNullOrEmpty(PrefReports))
      {
        result = true;
        var rp = PMS.Default.ReportsFolder;
        if (!string.IsNullOrEmpty(rp)
          && Directory.Exists(rp))
            PrefReports = OPS.Default.PrefReportsDir = rp;
        else
          PrefReports = OPS.Default.PrefReportsDir =
            AUS.Default.AppDir + "\\" + APS.Default.Home +
            "\\" + PMS.Default.Reports;
      }
      if (PMS.Default.Bac_dataCollection.Equals(null))
      {
        result = true;
        PMS.Default.Bac_dataCollection = new StringCollection();
      }
      if (PMS.Default.Bac_reportsCollection.Equals(null))
      {
        result = true;
        PMS.Default.Bac_reportsCollection = new StringCollection();
      }
      if (result) OPS.Default.Save();
 
      return result;
    }
 
    // ^v Both Return true if anything has changed.
    private bool CheckCollections()
    {
      var line1 = Data;
      var line2 = Reports;
      CreateNewDetectionStrings();
      return !line1.Equals(Data) || !line2.Equals(Reports);
    }
#endregion Upgrade 4.7.0.07 Apr 13 2017
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
#endregion Alternate Folder Finder
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
 
 
  }
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎