예제 #1
0
        /// <summary>
        /// Show the Open File dialogue, then load the selected character.
        /// </summary>
        private void OpenFile(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Filter      = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*",
                Multiselect = true
            };

            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                Timekeeper.Start("load_sum");
                Cursor = Cursors.WaitCursor;
                Character[] lstCharacters     = new Character[openFileDialog.FileNames.Length];
                object      lstCharactersLock = new object();
                Parallel.For(0, lstCharacters.Length, i =>
                {
                    Character objLoopCharacter = LoadCharacter(openFileDialog.FileNames[i]);
                    lock (lstCharactersLock)
                        lstCharacters[i] = objLoopCharacter;
                });
                Cursor = Cursors.Default;
                Program.MainForm.OpenCharacterList(lstCharacters);
                Application.DoEvents();
                Timekeeper.Finish("load_sum");
                Timekeeper.Log();
            }
        }
예제 #2
0
        public void Dispose()
        {
            Timekeeper.Finish(this.OperationName);
            this.Stop();
            switch (MyOperationType)
            {
            case OperationType.DependencyOperation:
                MyDependencyTelemetry.Duration = DateTimeOffset.UtcNow - MyDependencyTelemetry.Timestamp;
                if (MyDependencyTelemetry.ResultCode == "not disposed")
                {
                    MyDependencyTelemetry.ResultCode = "OK";
                }
                tc.TrackDependency(MyDependencyTelemetry);
                break;

            case OperationType.RequestOperation:
                MyRequestTelemetry.Duration = DateTimeOffset.UtcNow - MyRequestTelemetry.Timestamp;
                if (MyRequestTelemetry.ResponseCode == "not disposed")
                {
                    MyRequestTelemetry.ResponseCode = "OK";
                }
                tc.TrackRequest(MyRequestTelemetry);
                break;

            default:
                throw new NotImplementedException("Implement OperationType " + OperationName);
            }
        }
예제 #3
0
        /// <summary>
        /// Open the correct windows for a list of characters (not thread-safe).
        /// </summary>
        /// <param name="lstCharacters">Characters for which windows should be opened.</param>
        public void OpenCharacterList(IEnumerable <Character> lstCharacters, bool blnIncludeInMRU = true)
        {
            if (lstCharacters == null)
            {
                return;
            }

            Cursor = Cursors.WaitCursor;

            foreach (Character objCharacter in lstCharacters)
            {
                if (objCharacter == null)
                {
                    continue;
                }
                Timekeeper.Start("load_event_time");
                // Show the character form.
                if (!objCharacter.Created)
                {
                    frmCreate frmCharacter = new frmCreate(objCharacter)
                    {
                        MdiParent   = this,
                        WindowState = FormWindowState.Maximized,
                        Loading     = true
                    };
                    frmCharacter.Show();
                }
                else
                {
                    frmCareer frmCharacter = new frmCareer(objCharacter)
                    {
                        MdiParent   = this,
                        WindowState = FormWindowState.Maximized,
                        Loading     = true
                    };
                    frmCharacter.DiceRollerOpened    += objCareer_DiceRollerOpened;
                    frmCharacter.DiceRollerOpenedInt += objCareer_DiceRollerOpenedInt;
                    frmCharacter.Show();
                }

                if (blnIncludeInMRU)
                {
                    GlobalOptions.AddToMRUList(objCharacter.FileName);
                }

                objCharacter.CharacterNameChanged += objCharacter_CharacterNameChanged;
                objCharacter_CharacterNameChanged(objCharacter);
                Timekeeper.Finish("load_event_time");
            }

            Cursor = Cursors.Default;
        }
예제 #4
0
        /// <summary>
        /// Show the Open File dialogue, then load the selected character.
        /// </summary>
        private void OpenFile(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Filter      = "Chummer5 Files (*.chum5)|*.chum5|All Files (*.*)|*.*";
            openFileDialog.Multiselect = true;

            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                Timekeeper.Start("load_sum");
                foreach (string strFileName in openFileDialog.FileNames)
                {
                    LoadCharacter(strFileName);
                    Timekeeper.Start("load_event_time");
                    Application.DoEvents();
                    Timekeeper.Finish("load_event_time");
                }
                Timekeeper.Finish("load_sum");
                Timekeeper.Log();
            }
        }
예제 #5
0
        protected virtual void Dispose(bool blnIsDisposing)
        {
            if (_blnDisposed)
            {
                return;
            }

            if (blnIsDisposing)
            {
                Timekeeper.Finish(OperationName);
                Stop();
                switch (MyOperationType)
                {
                case OperationType.DependencyOperation:
                    MyDependencyTelemetry.Duration = DateTimeOffset.UtcNow - MyDependencyTelemetry.Timestamp;
                    if (MyDependencyTelemetry.ResultCode == "not disposed")
                    {
                        MyDependencyTelemetry.ResultCode = "OK";
                    }
                    tc.TrackDependency(MyDependencyTelemetry);
                    break;

                case OperationType.RequestOperation:
                    MyRequestTelemetry.Duration = DateTimeOffset.UtcNow - MyRequestTelemetry.Timestamp;
                    if (MyRequestTelemetry.ResponseCode == "not disposed")
                    {
                        MyRequestTelemetry.ResponseCode = "OK";
                    }
                    tc.TrackRequest(MyRequestTelemetry);
                    break;

                default:
                    throw new NotImplementedException("Implement OperationType " + OperationName);
                }
            }

            _blnDisposed = true;
        }
예제 #6
0
        /// <summary>
        /// Load a Character and open the correct window.
        /// </summary>
        /// <param name="strFileName">File to load.</param>
        /// <param name="blnIncludeInMRU">Whether or not the file should appear in the MRU list.</param>
        /// <param name="strNewName">New name for the character.</param>
        /// <param name="blnClearFileName">Whether or not the name of the save file should be cleared.</param>
        public void LoadCharacter(string strFileName, bool blnIncludeInMRU = true, string strNewName = "", bool blnClearFileName = false)
        {
            if (File.Exists(strFileName) && strFileName.EndsWith("chum5"))
            {
                Timekeeper.Start("loading");
                bool      blnLoaded    = false;
                Character objCharacter = new Character();
                objCharacter.FileName = strFileName;
                Timekeeper.Start("load_file");
                blnLoaded = objCharacter.Load();
                Timekeeper.Finish("load_file");
                Timekeeper.Start("load_free");
                if (!blnLoaded)
                {
                    return;
                }

                // If a new name is given, set the character's name to match (used in cloning).
                if (strNewName != "")
                {
                    objCharacter.Name = strNewName;
                }
                // Clear the File Name field so that this does not accidentally overwrite the original save file (used in cloning).
                if (blnClearFileName)
                {
                    objCharacter.FileName = "";
                }

                // Show the character form.
                if (!objCharacter.Created)
                {
                    frmCreate frmCharacter = new frmCreate(objCharacter);
                    frmCharacter.MdiParent   = this;
                    frmCharacter.WindowState = FormWindowState.Maximized;
                    frmCharacter.Loading     = true;
                    frmCharacter.Show();
                }
                else
                {
                    frmCareer frmCharacter = new frmCareer(objCharacter);
                    frmCharacter.MdiParent            = this;
                    frmCharacter.WindowState          = FormWindowState.Maximized;
                    frmCharacter.Loading              = true;
                    frmCharacter.DiceRollerOpened    += objCareer_DiceRollerOpened;
                    frmCharacter.DiceRollerOpenedInt += objCareer_DiceRollerOpenedInt;
                    frmCharacter.Show();
                }

                if (blnIncludeInMRU)
                {
                    GlobalOptions.Instance.AddToMRUList(strFileName);
                }

                objCharacter.CharacterNameChanged += objCharacter_CharacterNameChanged;
                objCharacter_CharacterNameChanged(objCharacter);
            }
            else
            {
                MessageBox.Show(LanguageManager.Instance.GetString("Message_FileNotFound").Replace("{0}", strFileName), LanguageManager.Instance.GetString("MessageTitle_FileNotFound"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
예제 #7
0
        public frmMain()
        {
            InitializeComponent();
            Version version           = Assembly.GetExecutingAssembly().GetName().Version;
            string  strCurrentVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);

            this.Text = string.Format("Chummer 5a - Version " + strCurrentVersion);

#if DEBUG
            Text += " DEBUG BUILD";
#endif

            LanguageManager.Instance.Load(GlobalOptions.Instance.Language, this);

            /** Dashboard **/
            //this.toolsMenu.DropDownItems.Add("GM Dashboard").Click += this.dashboardToolStripMenuItem_Click;
            /** End Dashboard **/

            // If Automatic Updates are enabled, check for updates immediately.
            if (GlobalOptions.Instance.AutomaticUpdate)
            {
                frmUpdate frmAutoUpdate = new frmUpdate();
                frmAutoUpdate.SilentMode = true;
                frmAutoUpdate.Visible    = false;
                frmAutoUpdate.ShowDialog(this);
            }
            else
            {
#if RELEASE
                frmUpdate frmAutoUpdate = new frmUpdate();
                frmAutoUpdate.GetChummerVersion();
                Version verCurrentVersion = new Version(strCurrentVersion);
                Version verLatestVersion  = new Version(frmAutoUpdate.LatestVersion);

                var result = verCurrentVersion.CompareTo(verLatestVersion);
                if (result != 0)
                {
                    this.Text += String.Format(" - Update {0} now available!", verLatestVersion);
                }
#endif
            }

            GlobalOptions.Instance.MRUChanged += PopulateMRU;

            // Delete the old executable if it exists (created by the update process).
            if (File.Exists("Chummer.exe.old"))
            {
                try
                {
                    File.Delete("Chummer.exe.old");
                }
                catch
                {
                }
            }

            // Populate the MRU list.
            PopulateMRU();

            // Retrieve the arguments passed to the application. If more than 1 is passed, we're being given the name of a file to open.
            string[] strArgs = Environment.GetCommandLineArgs();
            if (strArgs.GetUpperBound(0) > 0)
            {
                if (strArgs[1] != "/debug")
                {
                    LoadCharacter(strArgs[1]);
                }
                if (strArgs.Length > 2)
                {
                    if (strArgs[2] == "/test")
                    {
                        frmTest frmTestData = new frmTest();
                        frmTestData.Show();
                    }
                }
            }

            GlobalOptions.Instance.MainForm = this;

            // Set the Tag for each ToolStrip item so it can be translated.
            foreach (ToolStripMenuItem objItem in menuStrip.Items.OfType <ToolStripMenuItem>())
            {
                if (objItem.Tag != null)
                {
                    objItem.Text = LanguageManager.Instance.GetString(objItem.Tag.ToString());
                }
            }

            // ToolStrip Items.
            foreach (ToolStrip objToolStrip in this.Controls.OfType <ToolStrip>())
            {
                foreach (ToolStripButton objButton in objToolStrip.Items.OfType <ToolStripButton>())
                {
                    if (objButton.Tag != null)
                    {
                        objButton.Text = LanguageManager.Instance.GetString(objButton.Tag.ToString());
                    }
                }
            }

            // Attempt to cache the XML files that are used the most.
            try
            {
                Timekeeper.Start("cache_load");
                XmlManager.Instance.Load("armor.xml");
                XmlManager.Instance.Load("bioware.xml");
                XmlManager.Instance.Load("books.xml");
                XmlManager.Instance.Load("cyberware.xml");
                XmlManager.Instance.Load("gear.xml");
                XmlManager.Instance.Load("lifestyles.xml");
                XmlManager.Instance.Load("metatypes.xml");
                XmlManager.Instance.Load("qualities.xml");
                XmlManager.Instance.Load("ranges.xml");
                XmlManager.Instance.Load("skills.xml");
                XmlManager.Instance.Load("vehicles.xml");
                XmlManager.Instance.Load("weapons.xml");
                Timekeeper.Finish("cache_load");
            }
            catch
            {
            }
        }
예제 #8
0
        public frmChummerMain()
        {
            InitializeComponent();
            _strCurrentVersion = $"{_objCurrentVersion.Major}.{_objCurrentVersion.Minor}.{_objCurrentVersion.Build}";
            this.Text          = "Chummer 5a - Version " + _strCurrentVersion;
#if DEBUG
            Text += " DEBUG BUILD";
#endif

            LanguageManager.Load(GlobalOptions.Language, this);

            /** Dashboard **/
            //this.toolsMenu.DropDownItems.Add("GM Dashboard").Click += this.dashboardToolStripMenuItem_Click;
            /** End Dashboard **/

            // If Automatic Updates are enabled, check for updates immediately.

#if !DEBUG
            _workerVersionUpdateChecker.WorkerReportsProgress      = false;
            _workerVersionUpdateChecker.WorkerSupportsCancellation = false;
            _workerVersionUpdateChecker.DoWork             += DoCacheGitVersion;
            _workerVersionUpdateChecker.RunWorkerCompleted += CheckForUpdate;
            Application.Idle += IdleUpdateCheck;
            _workerVersionUpdateChecker.RunWorkerAsync();
#endif

            GlobalOptions.MRUChanged += PopulateMRUToolstripMenu;

            // Delete the old executable if it exists (created by the update process).
            foreach (string strLoopOldFilePath in Directory.GetFiles(Application.StartupPath, "*.old", SearchOption.AllDirectories))
            {
                if (File.Exists(strLoopOldFilePath))
                {
                    File.Delete(strLoopOldFilePath);
                }
            }

            // Populate the MRU list.
            PopulateMRUToolstripMenu();

            Program.MainForm = this;

            // Set the Tag for each ToolStrip item so it can be translated.
            foreach (ToolStripMenuItem objItem in menuStrip.Items.OfType <ToolStripMenuItem>())
            {
                if (objItem.Tag != null)
                {
                    objItem.Text = LanguageManager.GetString(objItem.Tag.ToString());
                }
            }

            // ToolStrip Items.
            foreach (ToolStrip objToolStrip in Controls.OfType <ToolStrip>())
            {
                foreach (ToolStripButton objButton in objToolStrip.Items.OfType <ToolStripButton>())
                {
                    if (objButton.Tag != null)
                    {
                        objButton.Text = LanguageManager.GetString(objButton.Tag.ToString());
                    }
                }
            }

            // Attempt to cache all XML files that are used the most.
            Timekeeper.Start("cache_load");
            Parallel.Invoke(
                () => XmlManager.Load("armor.xml"),
                () => XmlManager.Load("bioware.xml"),
                () => XmlManager.Load("books.xml"),
                () => XmlManager.Load("complexforms.xml"),
                () => XmlManager.Load("contacts.xml"),
                () => XmlManager.Load("critters.xml"),
                () => XmlManager.Load("critterpowers.xml"),
                () => XmlManager.Load("cyberware.xml"),
                //() => XmlManager.Load("drugcomponents.xml"), TODO: Re-enable when Custom Drugs branch is merged
                () => XmlManager.Load("echoes.xml"),
                () => XmlManager.Load("gameplayoptions.xml"),
                () => XmlManager.Load("gear.xml"),
                () => XmlManager.Load("improvements.xml"),
                () => XmlManager.Load("licenses.xml"),
                () => XmlManager.Load("lifemodules.xml"),
                () => XmlManager.Load("lifestyles.xml"),
                () => XmlManager.Load("martialarts.xml"),
                () => XmlManager.Load("mentors.xml"),
                () => XmlManager.Load("metamagic.xml"),
                () => XmlManager.Load("metatypes.xml"),
                () => XmlManager.Load("options.xml"),
                () => XmlManager.Load("packs.xml"),
                () => XmlManager.Load("powers.xml"),
                () => XmlManager.Load("priorities.xml"),
                () => XmlManager.Load("programs.xml"),
                () => XmlManager.Load("qualities.xml"),
                () => XmlManager.Load("ranges.xml"),
                () => XmlManager.Load("sheets.xml"),
                () => XmlManager.Load("skills.xml"),
                () => XmlManager.Load("spells.xml"),
                () => XmlManager.Load("spiritpowers.xml"),
                () => XmlManager.Load("traditions.xml"),
                () => XmlManager.Load("vehicles.xml"),
                () => XmlManager.Load("weapons.xml")
                );
            Timekeeper.Finish("cache_load");

            frmCharacterRoster frmCharacter = new frmCharacterRoster
            {
                MdiParent = this
            };
            _frmCharacterRoster = frmCharacter;

            // Retrieve the arguments passed to the application. If more than 1 is passed, we're being given the name of a file to open.
            string[]         strArgs                 = Environment.GetCommandLineArgs();
            string           strLoop                 = string.Empty;
            List <Character> lstCharactersToLoad     = new List <Character>();
            object           lstCharactersToLoadLock = new object();
            bool             blnShowTest             = false;
            object           blnShowTestLock         = new object();
            Parallel.For(1, strArgs.Length, i =>
            {
                strLoop = strArgs[i];
                if (strLoop == "/test")
                {
                    lock (blnShowTestLock)
                        blnShowTest = true;
                }
                else if (!strLoop.StartsWith('/'))
                {
                    Character objLoopCharacter = LoadCharacter(strLoop);
                    lock (lstCharactersToLoadLock)
                        lstCharactersToLoad.Add(objLoopCharacter);
                }
            });

            if (blnShowTest)
            {
                frmTest frmTestData = new frmTest();
                frmTestData.Show();
            }
            OpenCharacterList(lstCharactersToLoad);

            frmCharacter.WindowState = FormWindowState.Maximized;
            frmCharacter.Show();
        }
예제 #9
0
        /// <summary>
        /// Load a Character from a file and return it (thread-safe).
        /// </summary>
        /// <param name="strFileName">File to load.</param>
        /// <param name="blnIncludeInMRU">Whether or not the file should appear in the MRU list.</param>
        /// <param name="strNewName">New name for the character.</param>
        /// <param name="blnClearFileName">Whether or not the name of the save file should be cleared.</param>
        public Character LoadCharacter(string strFileName, string strNewName = "", bool blnClearFileName = false, bool blnShowErrors = true)
        {
            Character objCharacter = null;

            if (File.Exists(strFileName) && strFileName.EndsWith("chum5"))
            {
                Timekeeper.Start("loading");
                bool blnLoaded = false;
                objCharacter = new Character
                {
                    FileName = strFileName
                };

                XmlDocument objXmlDocument = new XmlDocument();
                //StreamReader is used to prevent encoding errors
                using (StreamReader sr = new StreamReader(strFileName, true))
                {
                    try
                    {
                        objXmlDocument.Load(sr);
                    }
                    catch (XmlException ex)
                    {
                        if (blnShowErrors)
                        {
                            MessageBox.Show(LanguageManager.GetString("Message_FailedLoad").Replace("{0}", ex.Message), LanguageManager.GetString("MessageTitle_FailedLoad"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                        return(null);
                    }
                }
                XmlNode objXmlCharacter = objXmlDocument.SelectSingleNode("/character");
                if (!string.IsNullOrEmpty(objXmlCharacter?["appversion"]?.InnerText))
                {
                    string strVersion = objXmlCharacter["appversion"].InnerText;
                    if (strVersion.StartsWith("0."))
                    {
                        strVersion = strVersion.Substring(2);
                    }
                    Version.TryParse(strVersion, out Version verSavedVersion);
                    Version.TryParse("5.188.34", out Version verCorrectedVersion);
                    if (verCorrectedVersion != null && verSavedVersion != null)
                    {
                        int intResult = verSavedVersion.CompareTo(verCorrectedVersion);
                        //Check for typo in Corrupter quality and correct it
                        if (intResult == -1)
                        {
                            File.WriteAllText(strFileName, Regex.Replace(File.ReadAllText(strFileName), "Corruptor", "Corrupter"));
                        }
                    }
                }

                OpenCharacters.Add(objCharacter);
                Timekeeper.Start("load_file");
                blnLoaded = objCharacter.Load();
                Timekeeper.Finish("load_file");
                if (!blnLoaded)
                {
                    objCharacter.Dispose();
                    OpenCharacters.Remove(objCharacter);
                    return(null);
                }

                // If a new name is given, set the character's name to match (used in cloning).
                if (!string.IsNullOrEmpty(strNewName))
                {
                    objCharacter.Name = strNewName;
                }
                // Clear the File Name field so that this does not accidentally overwrite the original save file (used in cloning).
                if (blnClearFileName)
                {
                    objCharacter.FileName = string.Empty;
                }
            }
            else if (blnShowErrors)
            {
                MessageBox.Show(LanguageManager.GetString("Message_FileNotFound").Replace("{0}", strFileName), LanguageManager.GetString("MessageTitle_FileNotFound"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return(objCharacter);
        }
예제 #10
0
        /// <summary>
        /// Load a Character and open the correct window.
        /// </summary>
        /// <param name="strFileName">File to load.</param>
        /// <param name="blnIncludeInMRU">Whether or not the file should appear in the MRU list.</param>
        /// <param name="strNewName">New name for the character.</param>
        /// <param name="blnClearFileName">Whether or not the name of the save file should be cleared.</param>
        public void LoadCharacter(string strFileName, bool blnIncludeInMRU = true, string strNewName = "", bool blnClearFileName = false)
        {
            if (File.Exists(strFileName) && strFileName.EndsWith("chum5"))
            {
                Timekeeper.Start("loading");
                Cursor.Current = Cursors.WaitCursor;
                bool      blnLoaded    = false;
                Character objCharacter = new Character();
                objCharacter.FileName = strFileName;

                XmlDocument objXmlDocument = new XmlDocument();
                //StreamReader is used to prevent encoding errors
                using (StreamReader sr = new StreamReader(strFileName, true))
                {
                    try
                    {
                        objXmlDocument.Load(sr);
                    }
                    catch (XmlException ex)
                    {
                        MessageBox.Show(LanguageManager.GetString("Message_FailedLoad").Replace("{0}", ex.Message), LanguageManager.GetString("MessageTitle_FailedLoad"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }
                XmlNode objXmlCharacter = objXmlDocument.SelectSingleNode("/character");
                if (!string.IsNullOrEmpty(objXmlCharacter?["appversion"]?.InnerText))
                {
                    Version verSavedVersion;
                    Version verCorrectedVersion;
                    string  strVersion = objXmlCharacter["appversion"].InnerText;
                    if (strVersion.StartsWith("0."))
                    {
                        strVersion = strVersion.Substring(2);
                    }
                    Version.TryParse(strVersion, out verSavedVersion);
                    Version.TryParse("5.188.34", out verCorrectedVersion);
                    if (verCorrectedVersion != null && verSavedVersion != null)
                    {
                        int intResult = verSavedVersion.CompareTo(verCorrectedVersion);
                        //Check for typo in Corrupter quality and correct it
                        if (intResult == -1)
                        {
                            File.WriteAllText(strFileName, Regex.Replace(File.ReadAllText(strFileName), "Corruptor", "Corrupter"));
                        }
                    }
                }

                Timekeeper.Start("load_file");
                blnLoaded = objCharacter.Load();
                Timekeeper.Finish("load_file");
                Timekeeper.Start("load_free");
                if (!blnLoaded)
                {
                    Cursor.Current = Cursors.Default;
                    return;
                }

                // If a new name is given, set the character's name to match (used in cloning).
                if (!string.IsNullOrEmpty(strNewName))
                {
                    objCharacter.Name = strNewName;
                }
                // Clear the File Name field so that this does not accidentally overwrite the original save file (used in cloning).
                if (blnClearFileName)
                {
                    objCharacter.FileName = string.Empty;
                }

                // Show the character form.
                if (!objCharacter.Created)
                {
                    frmCreate frmCharacter = new frmCreate(objCharacter)
                    {
                        MdiParent   = this,
                        WindowState = FormWindowState.Maximized,
                        Loading     = true
                    };
                    frmCharacter.Show();
                }
                else
                {
                    frmCareer frmCharacter = new frmCareer(objCharacter)
                    {
                        MdiParent   = this,
                        WindowState = FormWindowState.Maximized,
                        Loading     = true
                    };
                    frmCharacter.DiceRollerOpened    += objCareer_DiceRollerOpened;
                    frmCharacter.DiceRollerOpenedInt += objCareer_DiceRollerOpenedInt;
                    frmCharacter.Show();
                }

                if (blnIncludeInMRU)
                {
                    GlobalOptions.AddToMRUList(strFileName);
                }

                objCharacter.CharacterNameChanged += objCharacter_CharacterNameChanged;
                objCharacter_CharacterNameChanged(objCharacter);
                Cursor.Current = Cursors.Default;
            }
            else
            {
                MessageBox.Show(LanguageManager.GetString("Message_FileNotFound").Replace("{0}", strFileName), LanguageManager.GetString("MessageTitle_FileNotFound"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
예제 #11
0
        public frmMain()
        {
            InitializeComponent();
            Version version           = Assembly.GetExecutingAssembly().GetName().Version;
            string  strCurrentVersion = $"{version.Major}.{version.Minor}.{version.Build}";

            Text = string.Format("Chummer 5a - Version " + strCurrentVersion);

#if DEBUG
            Text += " DEBUG BUILD";
#endif

            LanguageManager.Load(GlobalOptions.Language, this);

            /** Dashboard **/
            //this.toolsMenu.DropDownItems.Add("GM Dashboard").Click += this.dashboardToolStripMenuItem_Click;
            /** End Dashboard **/

            // If Automatic Updates are enabled, check for updates immediately.

#if RELEASE
            if (Utils.GitUpdateAvailable() > 0)
            {
                if (GlobalOptions.AutomaticUpdate)
                {
                    frmUpdate frmAutoUpdate = new frmUpdate();
                    frmAutoUpdate.SilentMode = true;
                    frmAutoUpdate.Visible    = false;
                    frmAutoUpdate.ShowDialog(this);
                }
                else
                {
                    this.Text += String.Format(" - Update {0} now available!", Utils.GitVersion());
                }
            }
#endif

            GlobalOptions.MRUChanged += PopulateMRU;

            // Delete the old executable if it exists (created by the update process).
            foreach (string strLoopOldFilePath in Directory.GetFiles(Application.StartupPath, "*.old"))
            {
                if (File.Exists(strLoopOldFilePath))
                {
                    File.Delete(strLoopOldFilePath);
                }
            }

            // Populate the MRU list.
            PopulateMRU();

            GlobalOptions.MainForm = this;

            // Set the Tag for each ToolStrip item so it can be translated.
            foreach (ToolStripMenuItem objItem in menuStrip.Items.OfType <ToolStripMenuItem>())
            {
                if (objItem.Tag != null)
                {
                    objItem.Text = LanguageManager.GetString(objItem.Tag.ToString());
                }
            }

            // ToolStrip Items.
            foreach (ToolStrip objToolStrip in Controls.OfType <ToolStrip>())
            {
                foreach (ToolStripButton objButton in objToolStrip.Items.OfType <ToolStripButton>())
                {
                    if (objButton.Tag != null)
                    {
                        objButton.Text = LanguageManager.GetString(objButton.Tag.ToString());
                    }
                }
            }

            // Attempt to cache all XML files that are used the most.
            Timekeeper.Start("cache_load");
            XmlManager.Load("armor.xml");
            XmlManager.Load("bioware.xml");
            XmlManager.Load("books.xml");
            XmlManager.Load("complexforms.xml");
            XmlManager.Load("contacts.xml");
            XmlManager.Load("critters.xml");
            XmlManager.Load("critterpowers.xml");
            XmlManager.Load("cyberware.xml");
            // XmlManager.Load("drugcomponents.xml"); TODO: Re-enable when Custom Drugs branch is merged
            XmlManager.Load("echoes.xml");
            XmlManager.Load("gameplayoptions.xml");
            XmlManager.Load("gear.xml");
            XmlManager.Load("improvements.xml");
            XmlManager.Load("licenses.xml");
            XmlManager.Load("lifemodules.xml");
            XmlManager.Load("lifestyles.xml");
            XmlManager.Load("martialarts.xml");
            XmlManager.Load("mentors.xml");
            XmlManager.Load("metamagic.xml");
            XmlManager.Load("metatypes.xml");
            XmlManager.Load("options.xml");
            XmlManager.Load("packs.xml");
            XmlManager.Load("powers.xml");
            XmlManager.Load("priorities.xml");
            XmlManager.Load("programs.xml");
            XmlManager.Load("qualities.xml");
            XmlManager.Load("ranges.xml");
            XmlManager.Load("skills.xml");
            XmlManager.Load("spells.xml");
            XmlManager.Load("spiritpowers.xml");
            XmlManager.Load("traditions.xml");
            XmlManager.Load("vehicles.xml");
            XmlManager.Load("weapons.xml");
            Timekeeper.Finish("cache_load");

            frmCharacterRoster frmCharacter = new frmCharacterRoster();
            frmCharacter.MdiParent = this;

            // Retrieve the arguments passed to the application. If more than 1 is passed, we're being given the name of a file to open.
            string[] strArgs = Environment.GetCommandLineArgs();
            string   strLoop = string.Empty;
            for (int i = 1; i < strArgs.Length; ++i)
            {
                strLoop = strArgs[i];
                if (strLoop == "/test")
                {
                    frmTest frmTestData = new frmTest();
                    frmTestData.Show();
                }
                else if (!strLoop.StartsWith('/'))
                {
                    LoadCharacter(strLoop);
                }
            }

            frmCharacter.WindowState = FormWindowState.Maximized;
            frmCharacter.Show();
        }
예제 #12
0
        private void frmMasterIndex_Load(object sender, EventArgs e)
        {
            using (var op_load_frm_masterindex = Timekeeper.StartSyncron("op_load_frm_masterindex", null, CustomActivity.OperationType.RequestOperation, null))
            {
                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_entries", op_load_frm_masterindex))
                {
                    ConcurrentBag <ListItem> lstItemsForLoading = new ConcurrentBag <ListItem>();
                    ConcurrentBag <ListItem> lstFileNamesWithItemsForLoading = new ConcurrentBag <ListItem>();
                    Parallel.ForEach(_lstFileNames, strFileName =>
                    {
                        XPathNavigator xmlBaseNode = XmlManager.Load(strFileName).GetFastNavigator().SelectSingleNode("/chummer");
                        if (xmlBaseNode != null)
                        {
                            bool blnLoopFileNameHasItems = false;
                            foreach (XPathNavigator xmlItemNode in xmlBaseNode.Select(".//*[source and page]"))
                            {
                                blnLoopFileNameHasItems = true;
                                string strName          = xmlItemNode.SelectSingleNode("name")?.Value;
                                string strDisplayName   = xmlItemNode.SelectSingleNode("translate")?.Value
                                                          ?? strName
                                                          ?? xmlItemNode.SelectSingleNode("id")?.Value
                                                          ?? LanguageManager.GetString("String_Unknown");
                                string strSource      = xmlItemNode.SelectSingleNode("source")?.Value;
                                string strPage        = xmlItemNode.SelectSingleNode("page")?.Value;
                                string strDisplayPage = xmlItemNode.SelectSingleNode("altpage")?.Value
                                                        ?? strPage;
                                string strEnglishNameOnPage = xmlItemNode.SelectSingleNode("nameonpage")?.Value
                                                              ?? strName;
                                string strTranslatedNameOnPage = xmlItemNode.SelectSingleNode("altnameonpage")?.Value
                                                                 ?? strDisplayName;
                                string strNotes = xmlItemNode.SelectSingleNode("altnotes")?.Value
                                                  ?? xmlItemNode.SelectSingleNode("notes")?.Value;
                                MasterIndexEntry objEntry = new MasterIndexEntry(
                                    strDisplayName,
                                    strFileName,
                                    new SourceString(strSource, strPage, GlobalOptions.DefaultLanguage),
                                    new SourceString(strSource, strDisplayPage, GlobalOptions.Language),
                                    strEnglishNameOnPage,
                                    strTranslatedNameOnPage);
                                lstItemsForLoading.Add(new ListItem(objEntry, strDisplayName));
                                if (!string.IsNullOrEmpty(strNotes))
                                {
                                    _dicCachedNotes.TryAdd(objEntry, strNotes);
                                }
                            }

                            if (blnLoopFileNameHasItems)
                            {
                                lstFileNamesWithItemsForLoading.Add(new ListItem(strFileName, strFileName));
                            }
                        }
                    });

                    foreach (ListItem objItem in lstItemsForLoading)
                    {
                        MasterIndexEntry objEntry        = (MasterIndexEntry)objItem.Value;
                        ListItem         objExistingItem = _lstItems.FirstOrDefault(x =>
                                                                                    ((MasterIndexEntry)x.Value).DisplayName.Equals(objEntry.DisplayName, StringComparison.OrdinalIgnoreCase) &&
                                                                                    ((MasterIndexEntry)x.Value).DisplaySource == objEntry.DisplaySource);
                        if (objExistingItem.Value == null)
                        {
                            _lstItems.Add(objItem); // Not using AddRange because of potential memory issues
                        }
                        else
                        {
                            ((MasterIndexEntry)objExistingItem.Value).FileNames.UnionWith(objEntry.FileNames);
                        }
                    }
                    _lstFileNamesWithItems.AddRange(lstFileNamesWithItemsForLoading);
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_sort_entries", op_load_frm_masterindex))
                {
                    _lstItems.Sort(CompareListItems.CompareNames);
                    _lstFileNamesWithItems.Sort(CompareListItems.CompareNames);
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_controls", op_load_frm_masterindex))
                {
                    _lstFileNamesWithItems.Insert(0, new ListItem(string.Empty, LanguageManager.GetString("String_All")));

                    cboFile.BeginUpdate();
                    cboFile.ValueMember   = nameof(ListItem.Value);
                    cboFile.DisplayMember = nameof(ListItem.Name);
                    cboFile.DataSource    = _lstFileNamesWithItems;
                    cboFile.SelectedIndex = 0;
                    cboFile.EndUpdate();

                    lstItems.BeginUpdate();
                    lstItems.ValueMember   = nameof(ListItem.Value);
                    lstItems.DisplayMember = nameof(ListItem.Name);
                    lstItems.DataSource    = _lstItems;
                    lstItems.SelectedIndex = -1;
                    lstItems.EndUpdate();

                    _blnSkipRefresh = false;
                }
            }
        }
예제 #13
0
        private void DoImport()
        {
            TreeNode objSelectedNode = treCharacterList.SelectedNode;

            if (objSelectedNode != null && objSelectedNode.Level > 0)
            {
                int intIndex = Convert.ToInt32(objSelectedNode.Tag);
                if (intIndex >= 0 && intIndex < _lstCharacterCache.Count)
                {
                    string strFile        = _lstCharacterCache[intIndex]?.FilePath;
                    string strCharacterId = _lstCharacterCache[intIndex]?.CharacterId;
                    if (!string.IsNullOrEmpty(strFile) && !string.IsNullOrEmpty(strCharacterId))
                    {
                        string strFilePath  = Path.Combine(Application.StartupPath, "settings", "default.xml");
                        Cursor objOldCursor = Cursor;
                        if (!File.Exists(strFilePath))
                        {
                            if (MessageBox.Show(LanguageManager.GetString("Message_CharacterOptions_OpenOptions", GlobalOptions.Language), LanguageManager.GetString("MessageTitle_CharacterOptions_OpenOptions", GlobalOptions.Language), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                            {
                                Cursor = Cursors.WaitCursor;
                                frmOptions frmOptions = new frmOptions();
                                frmOptions.ShowDialog();
                                Cursor = objOldCursor;
                            }
                        }
                        Cursor                = Cursors.WaitCursor;
                        cmdImport.Enabled     = false;
                        cmdSelectFile.Enabled = false;
                        Character objCharacter  = new Character();
                        string    settingsPath  = Path.Combine(Application.StartupPath, "settings");
                        string[]  settingsFiles = Directory.GetFiles(settingsPath, "*.xml");

                        if (settingsFiles.Length > 1)
                        {
                            frmSelectSetting frmPickSetting = new frmSelectSetting();
                            frmPickSetting.ShowDialog(this);

                            if (frmPickSetting.DialogResult == DialogResult.Cancel)
                            {
                                return;
                            }

                            objCharacter.SettingsFile = frmPickSetting.SettingsFile;
                        }
                        else
                        {
                            string strSettingsFile = settingsFiles[0];
                            objCharacter.SettingsFile = Path.GetFileName(strSettingsFile);
                        }

                        Program.MainForm.OpenCharacters.Add(objCharacter);
                        Timekeeper.Start("load_file");
                        bool blnLoaded = objCharacter.LoadFromHeroLabFile(strFile, strCharacterId, objCharacter.SettingsFile);
                        Timekeeper.Finish("load_file");
                        if (!blnLoaded)
                        {
                            Program.MainForm.OpenCharacters.Remove(objCharacter);
                            objCharacter.DeleteCharacter();
                            Cursor                = objOldCursor;
                            cmdImport.Enabled     = true;
                            cmdSelectFile.Enabled = true;
                            return;
                        }

                        Program.MainForm.OpenCharacter(objCharacter);
                        Close();
                    }
                }
            }
        }
예제 #14
0
        private async ValueTask LoadContent()
        {
            using (CustomActivity opLoadMasterindex = Timekeeper.StartSyncron("op_load_frm_masterindex", null,
                                                                              CustomActivity.OperationType.RequestOperation, null))
            {
                _dicCachedNotes.Clear();
                foreach (MasterIndexEntry objExistingEntry in _lstItems.Select(x => x.Value))
                {
                    objExistingEntry.Dispose();
                }
                _lstItems.Clear();
                _lstFileNamesWithItems.Clear();
                string strSourceFilter;
                using (new FetchSafelyFromPool <HashSet <string> >(Utils.StringHashSetPool,
                                                                   out HashSet <string> setValidCodes))
                {
                    foreach (XPathNavigator xmlBookNode in (await XmlManager.LoadXPathAsync(
                                                                "books.xml", _objSelectedSetting.EnabledCustomDataDirectoryPaths))
                             .SelectAndCacheExpression("/chummer/books/book/code"))
                    {
                        setValidCodes.Add(xmlBookNode.Value);
                    }

                    setValidCodes.IntersectWith(_objSelectedSetting.Books);

                    strSourceFilter = setValidCodes.Count > 0
                        ? '(' + string.Join(" or ", setValidCodes.Select(x => "source = " + x.CleanXPath())) + ')'
                        : "source";
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_andpopulate_entries",
                                                   opLoadMasterindex))
                {
                    ConcurrentBag <ListItem> lstItemsForLoading = new ConcurrentBag <ListItem>();
                    using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_entries", opLoadMasterindex))
                    {
                        ConcurrentBag <ListItem> lstFileNamesWithItemsForLoading = new ConcurrentBag <ListItem>();
                        // Prevents locking the UI thread while still benefitting from static scheduling of Parallel.ForEach
                        await Task.WhenAll(_astrFileNames.Select(strFileName => Task.Run(async() =>
                        {
                            XPathNavigator xmlBaseNode
                                = await XmlManager.LoadXPathAsync(strFileName,
                                                                  _objSelectedSetting.EnabledCustomDataDirectoryPaths);
                            xmlBaseNode = xmlBaseNode.SelectSingleNodeAndCacheExpression("/chummer");
                            if (xmlBaseNode == null)
                            {
                                return;
                            }
                            bool blnLoopFileNameHasItems = false;
                            foreach (XPathNavigator xmlItemNode in xmlBaseNode.SelectAndCacheExpression(
                                         ".//*[page and " +
                                         strSourceFilter + ']'))
                            {
                                blnLoopFileNameHasItems = true;
                                string strName          = xmlItemNode.SelectSingleNodeAndCacheExpression("name")?.Value;
                                string strDisplayName
                                    = xmlItemNode.SelectSingleNodeAndCacheExpression("translate")?.Value
                                      ?? strName
                                      ?? xmlItemNode.SelectSingleNodeAndCacheExpression("id")?.Value
                                      ?? await LanguageManager.GetStringAsync("String_Unknown");
                                string strSource      = xmlItemNode.SelectSingleNodeAndCacheExpression("source")?.Value;
                                string strPage        = xmlItemNode.SelectSingleNodeAndCacheExpression("page")?.Value;
                                string strDisplayPage = xmlItemNode.SelectSingleNodeAndCacheExpression("altpage")?.Value
                                                        ?? strPage;
                                string strEnglishNameOnPage
                                    = xmlItemNode.SelectSingleNodeAndCacheExpression("nameonpage")?.Value
                                      ?? strName;
                                string strTranslatedNameOnPage =
                                    xmlItemNode.SelectSingleNodeAndCacheExpression("altnameonpage")?.Value
                                    ?? strDisplayName;
                                string strNotes = xmlItemNode.SelectSingleNodeAndCacheExpression("altnotes")?.Value
                                                  ?? xmlItemNode.SelectSingleNodeAndCacheExpression("notes")?.Value;
                                MasterIndexEntry objEntry = new MasterIndexEntry(
                                    strDisplayName,
                                    strFileName,
                                    new SourceString(strSource, strPage, GlobalSettings.DefaultLanguage,
                                                     GlobalSettings.InvariantCultureInfo),
                                    new SourceString(strSource, strDisplayPage, GlobalSettings.Language,
                                                     GlobalSettings.CultureInfo),
                                    strEnglishNameOnPage,
                                    strTranslatedNameOnPage);
                                lstItemsForLoading.Add(new ListItem(objEntry, strDisplayName));
                                if (!string.IsNullOrEmpty(strNotes))
                                {
                                    _dicCachedNotes.TryAdd(objEntry, strNotes);
                                }
                            }

                            if (blnLoopFileNameHasItems)
                            {
                                lstFileNamesWithItemsForLoading.Add(new ListItem(strFileName, strFileName));
                            }
                        })));

                        _lstFileNamesWithItems.AddRange(lstFileNamesWithItemsForLoading);
                    }

                    using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_entries", opLoadMasterindex))
                    {
                        string strSpace = await LanguageManager.GetStringAsync("String_Space");

                        string strFormat = "{0}" + strSpace + "[{1}]";
                        Dictionary <string, List <ListItem> > dicHelper
                            = new Dictionary <string, List <ListItem> >(lstItemsForLoading.Count);
                        try
                        {
                            foreach (ListItem objItem in lstItemsForLoading)
                            {
                                if (!(objItem.Value is MasterIndexEntry objEntry))
                                {
                                    continue;
                                }
                                string strKey = objEntry.DisplayName.ToUpperInvariant();
                                if (dicHelper.TryGetValue(strKey, out List <ListItem> lstExistingItems))
                                {
                                    ListItem objExistingItem = lstExistingItems.Find(
                                        x => x.Value is MasterIndexEntry y &&
                                        objEntry.DisplaySource.Equals(y.DisplaySource));
                                    if (objExistingItem.Value is MasterIndexEntry objLoopEntry)
                                    {
                                        objLoopEntry.FileNames.UnionWith(objEntry.FileNames);
                                        objEntry.Dispose();
                                    }
                                    else
                                    {
                                        using (new FetchSafelyFromPool <List <ListItem> >(
                                                   Utils.ListItemListPool, out List <ListItem> lstItemsNeedingNameChanges))
                                        {
                                            lstItemsNeedingNameChanges.AddRange(lstExistingItems.FindAll(
                                                                                    x => x.Value is MasterIndexEntry y &&
                                                                                    !objEntry.FileNames.IsSubsetOf(y.FileNames)));
                                            if (lstItemsNeedingNameChanges.Count == 0)
                                            {
                                                _lstItems.Add(
                                                    objItem); // Not using AddRange because of potential memory issues
                                                lstExistingItems.Add(objItem);
                                            }
                                            else
                                            {
                                                ListItem objItemToAdd = new ListItem(
                                                    objItem.Value, string.Format(GlobalSettings.CultureInfo,
                                                                                 strFormat, objItem.Name,
                                                                                 string.Join(
                                                                                     ',' + strSpace, objEntry.FileNames)));
                                                _lstItems.Add(
                                                    objItemToAdd); // Not using AddRange because of potential memory issues
                                                lstExistingItems.Add(objItemToAdd);

                                                foreach (ListItem objToRename in lstItemsNeedingNameChanges)
                                                {
                                                    _lstItems.Remove(objToRename);
                                                    lstExistingItems.Remove(objToRename);

                                                    if (!(objToRename.Value is MasterIndexEntry objExistingEntry))
                                                    {
                                                        continue;
                                                    }
                                                    objItemToAdd = new ListItem(objToRename.Value, string.Format(
                                                                                    GlobalSettings.CultureInfo,
                                                                                    strFormat, objExistingEntry.DisplayName,
                                                                                    string.Join(
                                                                                        ',' + strSpace,
                                                                                        objExistingEntry.FileNames)));
                                                    _lstItems.Add(
                                                        objItemToAdd); // Not using AddRange because of potential memory issues
                                                    lstExistingItems.Add(objItemToAdd);
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    _lstItems.Add(objItem); // Not using AddRange because of potential memory issues
                                    List <ListItem> lstHelperItems = Utils.ListItemListPool.Get();
                                    lstHelperItems.Add(objItem);
                                    dicHelper.Add(strKey, lstHelperItems);
                                }
                            }
                        }
                        finally
                        {
                            foreach (List <ListItem> lstHelperItems in dicHelper.Values)
                            {
                                Utils.ListItemListPool.Return(lstHelperItems);
                            }
                        }
                    }
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_sort_entries", opLoadMasterindex))
                {
                    _lstItems.Sort(CompareListItems.CompareNames);
                    _lstFileNamesWithItems.Sort(CompareListItems.CompareNames);
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_controls", opLoadMasterindex))
                {
                    _lstFileNamesWithItems.Insert(0, new ListItem(string.Empty, await LanguageManager.GetStringAsync("String_All")));

                    int intOldSelectedIndex = cboFile.SelectedIndex;

                    cboFile.BeginUpdate();
                    cboFile.PopulateWithListItems(_lstFileNamesWithItems);
                    try
                    {
                        cboFile.SelectedIndex = Math.Max(intOldSelectedIndex, 0);
                    }
                    // For some reason, some unit tests will fire this exception even when _lstFileNamesWithItems is explicitly checked for having enough items
                    catch (ArgumentOutOfRangeException)
                    {
                        cboFile.SelectedIndex = -1;
                    }
                    cboFile.EndUpdate();

                    lstItems.BeginUpdate();
                    lstItems.PopulateWithListItems(_lstItems);
                    lstItems.SelectedIndex = -1;
                    lstItems.EndUpdate();

                    _blnSkipRefresh = false;
                }
            }
        }
예제 #15
0
        private async void frmMasterIndex_Load(object sender, EventArgs e)
        {
            using (var op_load_frm_masterindex = Timekeeper.StartSyncron("op_load_frm_masterindex", null, CustomActivity.OperationType.RequestOperation, null))
            {
                HashSet <string> setValidCodes = new HashSet <string>();
                foreach (XPathNavigator xmlBookNode in (await XmlManager.LoadXPathAsync("books.xml")).Select("/chummer/books/book/code"))
                {
                    setValidCodes.Add(xmlBookNode.Value);
                }

                string strSourceFilter = setValidCodes.Count > 0
                    ? new StringBuilder("(")
                                         .AppendJoin(" or ", setValidCodes.Select(x => "source = \'" + x + "\'"))
                                         .Append(')').ToString()
                    : "source";

                ConcurrentBag <ListItem> lstItemsForLoading = new ConcurrentBag <ListItem>();
                ConcurrentBag <ListItem> lstFileNamesWithItemsForLoading = new ConcurrentBag <ListItem>();
                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_entries", op_load_frm_masterindex))
                {
                    // Prevents locking the UI thread while still benefitting from static scheduling of Parallel.ForEach
                    await Task.Run(() =>
                    {
                        Parallel.ForEach(_lstFileNames, strFileName =>
                        {
                            XPathNavigator xmlBaseNode = XmlManager.LoadXPath(strFileName);
                            xmlBaseNode = xmlBaseNode.SelectSingleNode("/chummer");
                            if (xmlBaseNode == null)
                            {
                                return;
                            }
                            bool blnLoopFileNameHasItems = false;
                            foreach (XPathNavigator xmlItemNode in xmlBaseNode.Select(".//*[page and " +
                                                                                      strSourceFilter + ']'))
                            {
                                blnLoopFileNameHasItems = true;
                                string strName          = xmlItemNode.SelectSingleNode("name")?.Value;
                                string strDisplayName   = xmlItemNode.SelectSingleNode("translate")?.Value
                                                          ?? strName
                                                          ?? xmlItemNode.SelectSingleNode("id")?.Value
                                                          ?? LanguageManager.GetString("String_Unknown");
                                string strSource      = xmlItemNode.SelectSingleNode("source")?.Value;
                                string strPage        = xmlItemNode.SelectSingleNode("page")?.Value;
                                string strDisplayPage = xmlItemNode.SelectSingleNode("altpage")?.Value
                                                        ?? strPage;
                                string strEnglishNameOnPage = xmlItemNode.SelectSingleNode("nameonpage")?.Value
                                                              ?? strName;
                                string strTranslatedNameOnPage =
                                    xmlItemNode.SelectSingleNode("altnameonpage")?.Value
                                    ?? strDisplayName;
                                string strNotes = xmlItemNode.SelectSingleNode("altnotes")?.Value
                                                  ?? xmlItemNode.SelectSingleNode("notes")?.Value;
                                MasterIndexEntry objEntry = new MasterIndexEntry(
                                    strDisplayName,
                                    strFileName,
                                    new SourceString(strSource, strPage, GlobalOptions.DefaultLanguage,
                                                     GlobalOptions.InvariantCultureInfo),
                                    new SourceString(strSource, strDisplayPage, GlobalOptions.Language,
                                                     GlobalOptions.CultureInfo),
                                    strEnglishNameOnPage,
                                    strTranslatedNameOnPage);
                                lstItemsForLoading.Add(new ListItem(objEntry, strDisplayName));
                                if (!string.IsNullOrEmpty(strNotes))
                                {
                                    _dicCachedNotes.TryAdd(objEntry, strNotes);
                                }
                            }

                            if (blnLoopFileNameHasItems)
                            {
                                lstFileNamesWithItemsForLoading.Add(new ListItem(strFileName, strFileName));
                            }
                        });
                    });
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_entries", op_load_frm_masterindex))
                {
                    string strSpace  = LanguageManager.GetString("String_Space");
                    string strFormat = "{0}" + strSpace + "[{1}]";
                    Dictionary <string, List <ListItem> > dicHelper = new Dictionary <string, List <ListItem> >(lstItemsForLoading.Count);
                    foreach (ListItem objItem in lstItemsForLoading)
                    {
                        MasterIndexEntry objEntry = (MasterIndexEntry)objItem.Value;
                        string           strKey   = objEntry.DisplayName.ToUpperInvariant();
                        if (dicHelper.TryGetValue(strKey, out List <ListItem> lstExistingItems))
                        {
                            ListItem objExistingItem = lstExistingItems.FirstOrDefault(x =>
                                                                                       objEntry.DisplaySource.Equals(((MasterIndexEntry)x.Value).DisplaySource));
                            if (objExistingItem.Value != null)
                            {
                                ((MasterIndexEntry)objExistingItem.Value).FileNames.UnionWith(objEntry.FileNames);
                            }
                            else
                            {
                                List <ListItem> lstItemsNeedingNameChanges = lstExistingItems.Where(x => !objEntry.FileNames.IsSubsetOf(((MasterIndexEntry)x.Value).FileNames)).ToList();
                                if (lstItemsNeedingNameChanges.Count == 0)
                                {
                                    _lstItems.Add(objItem); // Not using AddRange because of potential memory issues
                                    lstExistingItems.Add(objItem);
                                }
                                else
                                {
                                    ListItem objItemToAdd = new ListItem(objItem.Value, string.Format(GlobalOptions.CultureInfo,
                                                                                                      strFormat, objItem.Name, string.Join(',' + strSpace, objEntry.FileNames)));
                                    _lstItems.Add(objItemToAdd); // Not using AddRange because of potential memory issues
                                    lstExistingItems.Add(objItemToAdd);

                                    foreach (ListItem objToRename in lstItemsNeedingNameChanges)
                                    {
                                        _lstItems.Remove(objToRename);
                                        lstExistingItems.Remove(objToRename);

                                        MasterIndexEntry objExistingEntry = (MasterIndexEntry)objToRename.Value;
                                        objItemToAdd = new ListItem(objToRename.Value, string.Format(GlobalOptions.CultureInfo,
                                                                                                     strFormat, objExistingEntry.DisplayName, string.Join(',' + strSpace, objExistingEntry.FileNames)));
                                        _lstItems.Add(objItemToAdd); // Not using AddRange because of potential memory issues
                                        lstExistingItems.Add(objItemToAdd);
                                    }
                                }
                            }
                        }
                        else
                        {
                            _lstItems.Add(objItem); // Not using AddRange because of potential memory issues
                            dicHelper.Add(strKey, new List <ListItem>(objItem.Yield()));
                        }
                    }
                    _lstFileNamesWithItems.AddRange(lstFileNamesWithItemsForLoading);
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_sort_entries", op_load_frm_masterindex))
                {
                    _lstItems.Sort(CompareListItems.CompareNames);
                    _lstFileNamesWithItems.Sort(CompareListItems.CompareNames);
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_controls", op_load_frm_masterindex))
                {
                    _lstFileNamesWithItems.Insert(0, new ListItem(string.Empty, LanguageManager.GetString("String_All")));

                    cboFile.BeginUpdate();
                    cboFile.PopulateWithListItems(_lstFileNamesWithItems);
                    try
                    {
                        cboFile.SelectedIndex = 0;
                    }
                    // For some reason, some unit tests will fire this exception even when _lstFileNamesWithItems is explicitly checked for having enough items
                    catch (ArgumentOutOfRangeException)
                    {
                        cboFile.SelectedIndex = -1;
                    }
                    cboFile.EndUpdate();

                    lstItems.BeginUpdate();
                    lstItems.PopulateWithListItems(_lstItems);
                    lstItems.SelectedIndex = -1;
                    lstItems.EndUpdate();

                    _blnSkipRefresh = false;
                }
            }
        }
        private void frmMasterIndex_Load(object sender, EventArgs e)
        {
            using (var op_load_frm_masterindex = Timekeeper.StartSyncron("op_load_frm_masterindex", null, CustomActivity.OperationType.RequestOperation, null))
            {
                HashSet <string> setValidCodes = new HashSet <string>();
                XmlNodeList      lstBookNodes  = XmlManager.Load("books.xml").SelectNodes("/chummer/books/book/code");
                if (lstBookNodes?.Count > 0)
                {
                    foreach (XmlNode xmlBookNode in lstBookNodes)
                    {
                        setValidCodes.Add(xmlBookNode.InnerText);
                    }
                }

                string strSourceFilter = setValidCodes.Count > 0
                    ? new StringBuilder("(")
                                         .AppendJoin(" or ", setValidCodes.Select(x => "source = \'" + x + "\'"))
                                         .Append(')').ToString()
                    : "source";

                ConcurrentBag <ListItem> lstItemsForLoading = new ConcurrentBag <ListItem>();
                ConcurrentBag <ListItem> lstFileNamesWithItemsForLoading = new ConcurrentBag <ListItem>();
                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_load_entries", op_load_frm_masterindex))
                {
                    Parallel.ForEach(_lstFileNames, strFileName =>
                    {
                        XPathNavigator xmlBaseNode = XmlManager.Load(strFileName).GetFastNavigator().SelectSingleNode("/chummer");
                        if (xmlBaseNode != null)
                        {
                            bool blnLoopFileNameHasItems = false;
                            foreach (XPathNavigator xmlItemNode in xmlBaseNode.Select(".//*[page and " + strSourceFilter + ']'))
                            {
                                blnLoopFileNameHasItems = true;
                                string strName          = xmlItemNode.SelectSingleNode("name")?.Value;
                                string strDisplayName   = xmlItemNode.SelectSingleNode("translate")?.Value
                                                          ?? strName
                                                          ?? xmlItemNode.SelectSingleNode("id")?.Value
                                                          ?? LanguageManager.GetString("String_Unknown");
                                string strSource      = xmlItemNode.SelectSingleNode("source")?.Value;
                                string strPage        = xmlItemNode.SelectSingleNode("page")?.Value;
                                string strDisplayPage = xmlItemNode.SelectSingleNode("altpage")?.Value
                                                        ?? strPage;
                                string strEnglishNameOnPage = xmlItemNode.SelectSingleNode("nameonpage")?.Value
                                                              ?? strName;
                                string strTranslatedNameOnPage = xmlItemNode.SelectSingleNode("altnameonpage")?.Value
                                                                 ?? strDisplayName;
                                string strNotes = xmlItemNode.SelectSingleNode("altnotes")?.Value
                                                  ?? xmlItemNode.SelectSingleNode("notes")?.Value;
                                MasterIndexEntry objEntry = new MasterIndexEntry(
                                    strDisplayName,
                                    strFileName,
                                    new SourceString(strSource, strPage, GlobalOptions.DefaultLanguage, GlobalOptions.InvariantCultureInfo),
                                    new SourceString(strSource, strDisplayPage, GlobalOptions.Language, GlobalOptions.CultureInfo),
                                    strEnglishNameOnPage,
                                    strTranslatedNameOnPage);
                                lstItemsForLoading.Add(new ListItem(objEntry, strDisplayName));
                                if (!string.IsNullOrEmpty(strNotes))
                                {
                                    _dicCachedNotes.TryAdd(objEntry, strNotes);
                                }
                            }

                            if (blnLoopFileNameHasItems)
                            {
                                lstFileNamesWithItemsForLoading.Add(new ListItem(strFileName, strFileName));
                            }
                        }
                    });
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_entries", op_load_frm_masterindex))
                {
                    string strSpace = LanguageManager.GetString("String_Space");
                    Dictionary <string, List <ListItem> > dicHelper = new Dictionary <string, List <ListItem> >(lstItemsForLoading.Count);
                    foreach (ListItem objItem in lstItemsForLoading)
                    {
                        MasterIndexEntry objEntry = (MasterIndexEntry)objItem.Value;
                        string           strKey   = objEntry.DisplayName.ToUpperInvariant();
                        if (dicHelper.TryGetValue(strKey, out List <ListItem> lstExistingItems))
                        {
                            ListItem objExistingItem = lstExistingItems.FirstOrDefault(x =>
                                                                                       objEntry.DisplaySource.Equals(((MasterIndexEntry)x.Value).DisplaySource));
                            if (objExistingItem.Value != null)
                            {
                                ((MasterIndexEntry)objExistingItem.Value).FileNames.UnionWith(objEntry.FileNames);
                            }
                            else
                            {
                                List <ListItem> lstItemsNeedingNameChanges = lstExistingItems.Where(x => !objEntry.FileNames.IsSubsetOf(((MasterIndexEntry)x.Value).FileNames)).ToList();
                                if (lstItemsNeedingNameChanges.Count == 0)
                                {
                                    _lstItems.Add(objItem); // Not using AddRange because of potential memory issues
                                    lstExistingItems.Add(objItem);
                                }
                                else
                                {
                                    ListItem objItemToAdd = new ListItem(objItem.Value,
                                                                         new StringBuilder(objItem.Name)
                                                                         .Append(strSpace).Append('[').AppendJoin(',' + strSpace, objEntry.FileNames).Append(']').ToString());
                                    _lstItems.Add(objItemToAdd); // Not using AddRange because of potential memory issues
                                    lstExistingItems.Add(objItemToAdd);

                                    foreach (ListItem objToRename in lstItemsNeedingNameChanges)
                                    {
                                        _lstItems.Remove(objToRename);
                                        lstExistingItems.Remove(objToRename);

                                        MasterIndexEntry objExistingEntry = (MasterIndexEntry)objToRename.Value;
                                        objItemToAdd = new ListItem(objToRename.Value,
                                                                    new StringBuilder(objExistingEntry.DisplayName)
                                                                    .Append(strSpace).Append('[').AppendJoin(',' + strSpace, objExistingEntry.FileNames).Append(']').ToString());
                                        _lstItems.Add(objItemToAdd); // Not using AddRange because of potential memory issues
                                        lstExistingItems.Add(objItemToAdd);
                                    }
                                }
                            }
                        }
                        else
                        {
                            _lstItems.Add(objItem); // Not using AddRange because of potential memory issues
                            dicHelper.Add(strKey, new List <ListItem>(objItem.Yield()));
                        }
                    }
                    _lstFileNamesWithItems.AddRange(lstFileNamesWithItemsForLoading);
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_sort_entries", op_load_frm_masterindex))
                {
                    _lstItems.Sort(CompareListItems.CompareNames);
                    _lstFileNamesWithItems.Sort(CompareListItems.CompareNames);
                }

                using (_ = Timekeeper.StartSyncron("load_frm_masterindex_populate_controls", op_load_frm_masterindex))
                {
                    _lstFileNamesWithItems.Insert(0, new ListItem(string.Empty, LanguageManager.GetString("String_All")));

                    cboFile.BeginUpdate();
                    cboFile.ValueMember   = nameof(ListItem.Value);
                    cboFile.DisplayMember = nameof(ListItem.Name);
                    cboFile.DataSource    = _lstFileNamesWithItems;
                    cboFile.SelectedIndex = 0;
                    cboFile.EndUpdate();

                    lstItems.BeginUpdate();
                    lstItems.ValueMember   = nameof(ListItem.Value);
                    lstItems.DisplayMember = nameof(ListItem.Name);
                    lstItems.DataSource    = _lstItems;
                    lstItems.SelectedIndex = -1;
                    lstItems.EndUpdate();

                    _blnSkipRefresh = false;
                }
            }
        }